Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
在java环境中,反射机制允许程序在执行时获取某各类自身的定义信息,例如属性和方法等也可以实现动态创建类的对象、变更属性的内容或执行特定的方法的功能。从而使java具有动态语言的特性,增强了程序的灵活性和可移植性。
通过反射你可以获取类的Field、Method、Constructor、Superclass、Interface、Annotation以及泛型和类所在的包等信息。
【1】Reflection功能与API
Java反射机制提供的功能:
1.在运行时判断任意一个对象所属的类型;
2.在运行时构造任意一个类的对象;
3.在运行时判断任意一个类所具有的成员变量和方法;
4.在运行时调用任意一个对象的方法,甚至可以调用private方法。
5.生成动态代理。
Java反射机制API:
实现java反射机制的API在java.lang.reflect包下,如下所示:
1.java.lang.Class类:代表一个类;
2.java.lang.reflect.Field类:代表类的成员变量;
3.java.lang.reflect.Method类:代表类的方法;
4.java.lang.reflect.Constructor类:代表类的构造方法;
5.java.lang.reflectArray类:提供了动态创建数组以及访问数组的元素的静态方法。该类中所有方法都是静态的。
【2】Class类与加载机制
① class类定义
在Object类中定义了以下的方法,此方法将被所有子类继承:
public final Class getClass()
以上的方法返回值的类型是一个Class类,此类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称。
可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个类的有关信息。
Class本身也是一个类;
Class 对象只能由系统建立对象;
一个类在 JVM 中只会有一个Class实例 ;
一个Class对象对应的是一个加载到JVM中的一个.class文件;
每个类的实例都会记得自己是由哪个 Class 实例所生成;
通过Class可以完整地得到一个类中的完整结构 。② class类常用方法
public Constructor<T> getConstructor(Class<?>... parameterTypes) |
获取自身的 public Constructor |
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) |
根据名字获取自身的Constructor |
这里Field示例总结如下:
# 获取自身和父类的所有的 public Field public Field[] getFields() throws SecurityException {} # 获取自身所有的Field,但不包括从父类继承下来的属性 public Field[] getDeclaredFields() throws SecurityException {} # 根据名字获取自身和父类的 public Field public Field getField(String name) # 根据名字获取自身的 Field public Field getDeclaredField(String name)
Field代码测试如下:
public class Father { public int a; private int b; protected int f; int g; } public class Son extends Father { int c; private String d; protected float e; public int h; } public class FieldTest { public static void main(String[] args) { Class cls = Son.class; try { Field c = cls.getDeclaredField("c"); System.out.println("getDeclaredField获取自身default :"+c); Field d = cls.getDeclaredField("d"); System.out.println("getDeclaredField获取自身private :"+d); Field e = cls.getDeclaredField("e"); System.out.println("getDeclaredField获取自身protected :"+e); Field h = cls.getDeclaredField("h"); System.out.println("getDeclaredField获取自身public :"+h); // 父类public获取不到 // Field a = cls.getDeclaredField("a"); // System.out.println("getDeclaredField获取父类public :"+a); // 父类private获取不到 // Field b = cls.getDeclaredField("b"); // System.out.println("getDeclaredField获取父类private :"+b); // 父类protected获取不到 // Field f = cls.getDeclaredField("f"); // System.out.println("getDeclaredField获取父类protected :"+f); // 父类default获取不到 // Field g = cls.getDeclaredField("g"); // System.out.println("getDeclaredField获取父类default :"+g); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("getDeclaredField "+e.getMessage()); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("getDeclaredField "+e.getMessage()); } try { // 自身default获取不到 // Field c = cls.getField("c"); // System.out.println("getField获取自身default :"+c); // 自身private获取不到 // Field d = cls.getField("d"); // System.out.println("getField获取自身private :"+d); // 自身protected获取不到 // Field e = cls.getField("e"); // System.out.println("getField获取自身protected :"+e); Field h = cls.getField("h"); System.out.println("getField获取自身public :"+h); Field a = cls.getField("a"); System.out.println("getField获取父类public :"+a); // 父类private获取不到 // Field b = cls.getField("b"); // System.out.println("getField获取父类private :"+b); // 父类protected获取不到 // Field f = cls.getField("f"); // System.out.println("getField获取父类protected :"+f); //父类default获取不到 // Field g = cls.getField("g"); // System.out.println("getField获取父类default :"+g); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("getField "+e.getMessage()); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("getField "+e.getMessage()); } // 获取自身所有,不包括父类属性 Field[] filed1 = cls.getDeclaredFields(); for ( Field f : filed1 ) { System.out.println("Declared Field :"+f.getName()); } // 获取所有public属性,包括父类的 Field[] filed2 = cls.getFields(); for ( Field f : filed2 ) { System.out.println("Field :"+f.getName()); } } }
Field测试结果如下:
getDeclaredField获取自身default :int com.web.test.Son.c getDeclaredField获取自身private :private java.lang.String com.web.test.Son.d getDeclaredField获取自身protected :protected float com.web.test.Son.e getDeclaredField获取自身public :public int com.web.test.Son.h getField获取自身public :public int com.web.test.Son.h getField获取父类public :public int com.web.test.Father.a Declared Field :c Declared Field :d Declared Field :e Declared Field :h Field :h Field :a
Method示例总结如下:
# 获取自身和父类的所有的 public Method public Method[] getMethods() throws SecurityException { # 获取自身所有的Method,但不包括从父类继承下来的方法 public Method[] getDeclaredMethods() throws SecurityException {} # 根据名字获取自身和父类的 public Method public Method getMethod(String name, Class<?>... parameterTypes) # 根据名字获取自身的 Method public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
Method代码测试如下:
public class Father { public int a; private int b; protected int f; int g; public void methodA(){ System.out.println("父类public methodA"); } private void methodB(){ System.out.println("父类private methodB"); } protected void methodF(){ System.out.println("父类protected methodF"); } void methodG(){ System.out.println("父类default methodG"); } } public class Son extends Father { int c; private int d; protected float e; public int h; void methodC(){ System.out.println("自身default methodC"); } private void methodD(){ System.out.println("自身private methodD"); } protected void methodE(){ System.out.println("自身protected methodE"); } public void methodH(){ System.out.println("自身public methodH"); } } public class MethodTest { public static void main(String[] args) { Class cls = Son.class; try { Method c = cls.getDeclaredMethod("methodC"); System.out.println("getDeclaredMethod获取自身default :"+c); Method d = cls.getDeclaredMethod("methodD"); System.out.println("getDeclaredMethod获取自身private :"+d); Method e = cls.getDeclaredMethod("methodE"); System.out.println("getDeclaredMethod获取自身protected :"+e); Method h = cls.getDeclaredMethod("methodH"); System.out.println("getDeclaredMethod获取自身public :"+h); // 父类public获取不到 // Method a = cls.getDeclaredMethod("methodA"); // System.out.println("getDeclaredMethod获取父类public :"+a); // 父类private获取不到 // Method b = cls.getDeclaredMethod("methodB"); // System.out.println("getDeclaredMethod获取父类private :"+b); // 父类protected获取不到 // Method f = cls.getDeclaredMethod("methodF"); // System.out.println("getDeclaredMethod获取父类protected :"+f); // 父类default获取不到 // Method g = cls.getDeclaredMethod("methodG"); // System.out.println("getDeclaredMethod获取父类default :"+g); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("getDeclaredMethod "+e.getMessage()); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("getDeclaredMethod "+e.getMessage()); } try { // 自身default获取不到 // Method c = cls.getMethod("methodC"); // System.out.println("getMethod获取自身default :"+c); // 自身private获取不到 // Method d = cls.getMethod("methodD"); // System.out.println("getMethod获取自身private :"+d); // 自身protected获取不到 // Method e = cls.getMethod("methodE"); // System.out.println("getMethod获取自身protected :"+e); Method h = cls.getMethod("methodH",null); System.out.println("getMethod获取自身public :"+h); Method a = cls.getMethod("methodA",null); System.out.println("getMethod获取父类public :"+a); // 父类private获取不到 // Method b = cls.getMethod("methodB"); // System.out.println("getMethod获取父类private :"+b); // 父类protected获取不到 // Method f = cls.getMethod("methodF"); // System.out.println("getMethod获取父类protected :"+f); //父类default获取不到 // Method g = cls.getMethod("methodG"); // System.out.println("getMethod获取父类default :"+g); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("getMethod "+e.getMessage()); }catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("getMethod "+e.getMessage()); } // 获取自身所有,不包括父类方法 Method[] method1 = cls.getDeclaredMethods(); for ( Method m : method1 ) { System.out.println("Declared Method :"+m.getName()); } // 获取所有public方法,包括父类的 Method[] method2 = cls.getMethods(); for ( Method m : method2 ) { System.out.println("Method :"+m.getName()); } } }
ethod测试结果如下:
getDeclaredMethod获取自身default :void com.web.test.Son.methodC() getDeclaredMethod获取自身private :private void com.web.test.Son.methodD() getDeclaredMethod获取自身protected :protected void com.web.test.Son.methodE() getDeclaredMethod获取自身public :public void com.web.test.Son.methodH() getMethod获取自身public :public void com.web.test.Son.methodH() getMethod获取父类public :public void com.web.test.Father.methodA() Declared Method :methodC Declared Method :methodD Declared Method :methodH Declared Method :methodE Method :methodH Method :methodA Method :wait Method :wait Method :wait Method :equals Method :toString Method :hashCode Method :getClass Method :notify Method :notifyAll
Constructor总结如下:
# 获取自身所有的 public Constructor public Constructor<?>[] getConstructors() throws SecurityException {} # 获取自身所有的Constructor--构造器不能继承 public Constructor<?>[] getDeclaredConstructors() throws SecurityException {} # 获取自身 public Constructor public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException {} # 获取自身的 Constructor public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException {
Constructor测试代码如下:
public class Father { public int a; private int b; protected int f; int g; public void methodA(){ System.out.println("父类public methodA"); } private void methodB(){ System.out.println("父类private methodB"); } protected void methodF(){ System.out.println("父类protected methodF"); } void methodG(){ System.out.println("父类default methodG"); } public Father(){ super(); } private Father(int b){ super(); this.b = b; } protected Father(int f,int b ){ super(); this.f = f; this.b = b; } Father(int f,int b,int g ){ super(); this.f = f; this.b = b; this.g = g; } public Father(int a,int f,int b,int g ){ super(); this.a = a; this.f = f; this.b = b; this.g = g; } } public class Son extends Father { int c; private int d; protected float e; public int h; void methodC(){ System.out.println("自身default methodC"); } private void methodD(){ System.out.println("自身private methodD"); } protected void methodE(){ System.out.println("自身protected methodE"); } public void methodH(){ System.out.println("自身public methodH"); } public Son(){ super(); } private Son(int d){ super(); this.d = d; } protected Son(int d,int e ){ super(); this.e = e; this.d = d; } Son(int c,int d,int e ){ super(); this.c = c; this.d = d; this.e = e; } } public class ConstructorTest { public static void main(String[] args) { Class cls = Son.class; try { Constructor<Son> c = cls.getDeclaredConstructor(int.class,int.class,int.class); System.out.println("getDeclaredConstructor获取自身default :"+c); Constructor<Son> d = cls.getDeclaredConstructor(int.class); System.out.println("getDeclaredConstructor获取自身private :"+d); Constructor<Son> e = cls.getDeclaredConstructor(int.class,int.class); System.out.println("getDeclaredConstructor获取自身protected :"+e); Constructor<Son> h = cls.getDeclaredConstructor(); System.out.println("getDeclaredConstructor获取自身public :"+h); } catch (NoSuchMethodException e) { e.printStackTrace(); System.out.println("getDeclaredConstructor "+e.getMessage()); } catch (SecurityException e) { e.printStackTrace(); System.out.println("getDeclaredConstructor "+e.getMessage()); } try { // 自身default获取不到 // Constructor<Son> c = cls.getConstructor(int.class,int.class,int.class); // System.out.println("getConstructor获取自身default :"+c); // 自身private获取不到 // Constructor<Son> d = cls.getConstructor(int.class); // System.out.println("getConstructor获取自身private :"+d); // 自身protected获取不到 // Constructor<Son> e = cls.getConstructor(int.class,int.class); // System.out.println("getConstructor获取自身protected :"+e); Constructor<Son> h = cls.getConstructor(); System.out.println("getConstructor获取自身public :"+h); // 父public can't get // Constructor constructor = cls.getConstructor(int.class,int.class,int.class,int.class); // System.out.println("getConstructor获取父public :"+constructor); } catch (SecurityException | NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("getConstructor "+e.getMessage()); } // 获取自身所有 Constructor Constructor[] constructors1 = cls.getDeclaredConstructors(); for ( Constructor c : constructors1 ) { System.out.println("Declared Constructor :"+c.getName()); } // 获取自身所有public Constructor Constructor[] constructors2 = cls.getConstructors(); for ( Constructor c : constructors2 ) { System.out.println("Constructor :"+c.getName()); } } }
Constructor测试结果如下:
getDeclaredConstructor获取自身default :com.web.test.Son(int,int,int) getDeclaredConstructor获取自身private :private com.web.test.Son(int) getDeclaredConstructor获取自身protected :protected com.web.test.Son(int,int) getDeclaredConstructor获取自身public :public com.web.test.Son() getConstructor获取自身public :public com.web.test.Son() Declared Constructor :com.web.test.Son Declared Constructor :com.web.test.Son Declared Constructor :com.web.test.Son Declared Constructor :com.web.test.Son Constructor :com.web.test.Son
③ 实例化类的四种方法
- 已知具体的类,通过类的class属性获取
Class clazz = String.class # 该方法最为安全可靠,程序性能最高
- 已知某个类的实例,调用该实例的getClass()方法获 取Class对象
Class clazz = person.getClass();
- 已知一个类的全类名,且该类在类路径下,可通过 Class类的静态方法forName()获取
Class clazz = Class.forName(“java.lang.String”); # 可能抛出ClassNotFoundException
- ClassLoader
ClassLoader cl = this.getClass().getClassLoader(); Class clazz = cl.loadClass(“类的全类名”);
【3】类的加载过程
当程序主动使用某个类时,如果该类还未被加载到内存中,则系统会通过如下三个步骤来对该类进行初始化。
【4】ClassLoader
类加载器是用来把类(class)装载进内存的。
JVM 规范定义了两种类型的类加载器:启动类加载器(bootstrap)和用户自定义加载器(user-defined class loader)。
JVM在运行时会产生3个类加载器组成的初始化加载器层次结构 ,如下图所示:
实例代码如下:
//1.获取一个系统类加载器 ClassLoader classloader = ClassLoader.getSystemClassLoader(); System.out.println(classloader); //2.获取系统类加载器的父类加载器,即扩展类加载器 classloader = classloader.getParent(); System.out.println(classloader); //3.获取扩展类加载器的父类加载器,即引导类加载器 classloader = classloader.getParent(); System.out.println(classloader); //4.测试当前类由哪个类加载器进行加载 classloader = Class.forName("exer2.ClassloaderDemo").getClassLoader(); System.out.println(classloader);
实例demo–动态创建数组对象:
/*,对数组元素赋值和取值*/ public void test(){ Class c = Class.forName("java.lang.String"); //create a String type Array,the length is 10 Object arr = Array.newInstance(c,10); //at the index =5 ,assignment the parameter value Array.set(arr,5,"this is a test"); //get the index=5 value String s = (String)Array.get(arr,5); System.out.println(s); }
【5】使用反射获取私有属性/方法
使用Class类中的方法可以获得该类中的所有Constructor对象,Method对象,和Field对象。
但是无法访问私有化的构造方法,普通方法,和私有属性,此时我们可以使用他们继承父类(AccessibleObject)中的setAccessible()方法,来设置或取消访问检查,以达到访问私有对象的目的。如下示例,获取私有属性(方法类同):
Field[] fields = Test.class.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { fields[i].setAccessible(true); try { System.out.println(fields[i].get(test)); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); }
其他点击查看反射详解参考