我们可以通过Java的RTTI机制可以获知某个对象的确切类型,但是这需要个先决条件:该类型必须在编译时必须已知,这样RTTI才能识别它,也就是说,在编译时,编译器必须要知道通过RTTI来处理的类。问题来了,如果我们不能获取的对象所属的实际类该怎么办?比如,我们从磁盘文件或网络中获取到一串字节,并被告知这些字节代表一个类,我们怎样才能使用这样的类呢?解决方案是利用Java反射机制,从字面意思理解,我们可以通过对象映射到该对象所属的类,从而获得对应类的信息,这就是反射。在Java类型信息之RTTI一节,我们获取对象所属类的方法信息时已经运用到了反射机制,Class类和java.lang.reflect类库一起对反射机制提供了支持,通过查询java.lang.reflect类库,先来个例子:
1 package re; 2 import java.util.*; 3 import java.lang.reflect.*; 4 public class Reflect{ 5 public static void main(String[] args)throws Exception{ 6 Class som=Class.forName("re.Some"); 7 Field[] fields=som.getDeclaredFields(); 8 Constructor[] ctors=som.getConstructors(); 9 Method[] methods=som.getMethods(); 10 print("fields of Some"); 11 for(Field field:fields){ 12 print(" "+field); 13 } 14 print("methods of some"); 15 for(Method method:methods){ 16 print(" "+method.toString()); 17 } 18 print("constructors of some"); 19 for(Constructor cto:ctors){ 20 print(" "+cto.toString()); 21 } 22 } 23 static void print(Object o){ 24 System.out.println(o); 25 } 26 } 27 class Some{ 28 private int val=0; 29 private String str=null; 30 public Some(){ 31 32 } 33 public void setString(String str){ 34 this.str=str; 35 } 36 public void setVal(int val){ 37 this.val=val; 38 } 39 public String getString(){ 40 return str; 41 } 42 public int getVal(){ 43 return val; 44 } 45 }
通过运行结果,我们获取到了Some类的成员变量、成员方法和构造方法,这里Class.forName()生成的结果在编译期是不可知的,所有的方法特征签名信息都是在运行时提取出来的,所以,虽然有时我们可能不能获取一个类,但是只要我们拿到这个类的对象,我们依然可以获取创建这个对象的类的大部分信息,这就是反射,通过运行时的对象信息反射出创建该对象的类信息。
以上是对《Thinking in Java》的学习总结,晚安,睡觉了...