14.类型信息
14.1为什么需要RTTI?
java通过以下两种方式在运行的时候获取类和对象的信息。
1.传统的RTTI(runtime type information),编译的时候
2.反射,运行的时候
3.Class对象包含了与类有关的信息。每个类都有一个Class对象,每当编写并且编译了一个新类,都 会产生一个Class对象,更确切的说,是被保存到一个同名的.class文件中。
4.JVM使用“类加载器”来生成Class对象。
14.2 Class对象
类是程序的一部分,每个类都有一个Class对象,换言之,每当编写编译一个新类,就会产生一个Class对象。为了生成这个类的对象,JVM需要使用“类加载器”。
类在什么时候被加载?
1.所有的类都在第一次使用时,被动态加载到JVM中。按需加载。
2.当程序创建第一个对类的静态成员的引用时,就会加载这个类。(这也证明构造器是类的无static标明的特殊静态方法)
static块
1.static{}(即static块),会在类被加载的时候执行且仅会被执行一次,一般用来初始化静态变量和调用静态方法
2.static块的执行顺序遵循定义顺序。
3.调用类的静态常量的时候,是不会加载类的,即不会执行static块。
4.用Class.forName()形式的时候,我们也可以自己设定要不要加载类。如将Class.forName("Test")改为Class.forName("Test",false,StaticBlockTest.class.getClassLoader()),你会发现程序什么都没有输出,即Test没有被加载,static{}没有被执行。
获取Class的几种方法
1.
Class.forName("com.nuaa.Test");
2.
Test test=new Test();
test.getClass();
3.Test.class//类字面常量
第3种方法不仅简单,而且更安全,因为他在编译时就会受到检查,不需要放在try...catch中。此外,.class方法不会让类被加载。
还可以应用于基本数据类型。
14.3 类型转换前先做检查
14.4 注册工厂
工厂方法设计模式,将对象的创建工作交给类自己去完成。
com/nuaa/typeInfomation/Factory.java
1 package com.nuaa.typeInformation; 2 3 public interface Factory<T> { 4 T create(); 5 }
com/nuaa/typeInfomation/RegisteredFactories.java
1 package com.nuaa.typeInformation; 2 3 4 class Part{ 5 public String toString(){ 6 return getClass().getSimpleName(); 7 } 8 } 9 10 class Filter extends Part{} 11 class FuelFilter extends Filter{ 12 public static class Factory implements com.nuaa.typeInformation.Factory<FuelFilter>{ 13 public FuelFilter create(){ 14 return new FuelFilter(); 15 } 16 } 17 18 String value1="hello world"; 19 20 public String getValue1() { 21 return value1; 22 } 23 24 public void setValue1(String value1) { 25 this.value1 = value1; 26 } 27 } 28 29 class AirFilter extends Filter{ 30 public static class Factory implements com.nuaa.typeInformation.Factory<AirFilter>{ 31 public AirFilter create(){ 32 return new AirFilter(); 33 } 34 } 35 } 36 37 class Belt extends Part{} 38 class FanBelt extends Belt{ 39 public static class Factory implements com.nuaa.typeInformation.Factory<FanBelt>{ 40 public FanBelt create(){ 41 return new FanBelt(); 42 } 43 } 44 } 45 46 47 48 public class RegisteredFactories { 49 public static void main(String[] args){ 50 System.out.println(new FuelFilter.Factory().create().getValue1()); 51 } 52 }
output:
hello world
14.5 instanceof和Class的等价性
instanceof、isInstance、equals和==
instanceof和isInstance显示结果一样,考虑了继承;
equals和==显示结果一样,未考虑继承。
14.6 反射:运行时的类信息
反射机制
适用情形:已知一个对象引用,但并不知道它所属的类。例如,从磁盘文件,或者网络连接中获取了一串字节,并且被告知是一个对象,那么我们该如何使用它呢?

package com.nuaa.typeInformation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; class PersonInfo{ String name; int age; String addr; //无参数 public String toString(){ String str=name+","+age+"addr"; System.out.println(str); return str; } //有参数 public void toString1(String arg){ System.out.println(arg); } } public class GetMethods { public static void main(String[] args){ Object obj=null; Class clazz=PersonInfo.class; try { obj=clazz.newInstance(); } catch (InstantiationException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (IllegalAccessException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } try { //Method method=clazz.getMethod("toString"); Method method=clazz.getMethod("toString1",String.class); try { method.invoke(obj); method.invoke(obj,"hello world"); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }

浙公网安备 33010602011771号