反射,就是获取运行中的程序中一个未知类的基本的信息并对这些基本信息进行操作的机制。
先贴一下相关的测试代码:
public class ReflectionTest { public static void main(String args[]){ try { Class c = Class.forName("test.Son"); Constructor[] cons1 = c.getConstructors(); Constructor[] cons2 = c.getDeclaredConstructors(); System.out.println("#c.getConstructors()"); for(Constructor con: cons1){ System.out.println(con.toString()); } // end for System.out.println("#c.getDeclaredConstructors()"); for(Constructor con : cons2){ System.out.println(con.toString()); } // end for Method[] meth1 = c.getMethods(); Method[] meth2 = c.getDeclaredMethods(); System.out.println("#c.getMethods()"); for(Method m: meth1){ System.out.println(m.toString()); } // end for System.out.println("#c.getDeclaredMethods()"); for(Method m : meth2){ System.out.println(m.toString()); } // end for Field[] field1 = c.getFields(); Field[] field2 = c.getDeclaredFields(); System.out.println("#c.getFields()"); for(Field f: field1){ System.out.println(f.toString()); } // end for System.out.println("#c.getDeclaredFields()"); for(Field f : field2){ System.out.println(f.toString()); } // end for } catch (ClassNotFoundException e) { e.printStackTrace(); } }}class Father{ String fName; public int a; public Father(){} public Father(String fName){ this.fName = fName; } // end constructor void fFun1(){System.out.println("Father.fFun1()");} void fFun2(String str){System.out.println("Father.fFun2()" + str);} public int fFun3(){System.out.println("Father.fFun3()");return 0;}} // end class Father// 子类class Son extends Father{ String sStr; public Son(String sStr){this.sStr = sStr;} public void sFun1(){System.out.println("Son.sFun1()");} public void sFun2(int i){System.out.println("Son.sFun2()");} void sFun3(){System.out.println("Son.sFun3()");}} // end class Son运行的结果如下:
#c.getConstructors()public test.Son(java.lang.String)#c.getDeclaredConstructors()public test.Son(java.lang.String)
#c.getMethods()public void test.Son.sFun1()public void test.Son.sFun2(int)public int test.Father.fFun3()public final native java.lang.Class java.lang.Object.getClass()public native int java.lang.Object.hashCode()public boolean java.lang.Object.equals(java.lang.Object)public java.lang.String java.lang.Object.toString()public final native void java.lang.Object.notify()public final native void java.lang.Object.notifyAll()public final void java.lang.Object.wait() throws java.lang.InterruptedExceptionpublic final void java.lang.Object.wait(long,int) throws java.lang.InterruptedExceptionpublic final native void java.lang.Object.wait(long) throws java.lang.InterruptedException#c.getDeclaredMethods()public void test.Son.sFun1()public void test.Son.sFun2(int)void test.Son.sFun3()
#c.getFields()public int test.Father.a#c.getDeclaredFields()java.lang.String test.Son.sStr
由于反射的概念是靠Class类和java.lang.reflect类库支撑起来的。因此我们要得到类的信息,就需要借助Method、Field以及Constructor等类。首先,我们需要先得到一个Class对象
getConstructors()方法返回的是当前类的所有public的构造器,而getDeclaredConstructors()方法返回的是当前类的所有构造器。
getMethods()方法得到的是该类及其父类的所有public方法,Object作为万物之父,它的方法出现在这里也就不足为奇了。Son.sFun3()方法只出现在了getDeclaredMethods()方法里,因为这个方法是用来得到当前类所有方法的。
使用getFields()方法时,并没有出现本类的field,而是父类的public属性,而getDeclaredFields()方法还是一样返回本类的所有属性
main方法也可以被继承,因此也会在子类getMethods()方法的结果中也会出现(前提是父类有main方法,但是一般没有人这么做);
获得恰当的Class对象的引用是反射和RTTI的前提和基石; Class对象仅在需要的时候才加载; java.lang.reflect类库中的类的对象是由JVM在运行时创建的。参考文档:
总结一下,这里只是一个简单的反射介绍,利用class,constructor,field及method获取类的信息