在Java中,反射机制能在运行状态中获取任意一个类的全部属性和方法,并能够对该类的某个对象获取其属性的值或执行某个方法。虽然使用反射会下降程序的性能,增长项目复杂度,可是适当的时候使用反射可使代码更加灵活,如动态代理。
这里重点记录下如何经过反射构造出内部类的实例。内部类分为成员内部类,局部内部类,静态内部类,匿名内部类,这里不考虑局部内部类状况了。 java
考虑以下类,须要经过反射建立其中三个内部类,匿名内部类是一个属性的值。这里三个内部类的访问权限都是private
的。apache
public class InnerContainer { public InnerContainer() { } private class InnerA { private String f = InnerA.class.getSimpleName(); public InnerA() { } } private static class InnerB { private String f = InnerB.class.getSimpleName(); public InnerB() {} } private Runnable r = new Runnable() { @Override public void run() { System.out.println("Method run of Runnable r"); } }; }
构造获取三个内部类的方法:ide
@SuppressWarnings({ "rawtypes", "unchecked" }) public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException { Class clazz = InnerContainer.class; InnerContainer container = (InnerContainer) clazz.newInstance(); Class innerClazz[] = clazz.getDeclaredClasses(); for (Class cls : innerClazz) { int mod = cls.getModifiers(); String modifier = Modifier.toString(mod); if (modifier.contains("static")) { //构造静态内部类实例 // Constructor con1 = cls.getDeclaredConstructor(); Object obj1 = cls.newInstance(); Field field1 = cls.getDeclaredField("f"); field1.setAccessible(true); System.out.println(field1.get(obj1)); } else { // 构形成员内部类实例 Constructor con2 = cls.getDeclaredConstructor(clazz); con2.setAccessible(true); Object obj2 = con2.newInstance(container); Field field2 = cls.getDeclaredField("f"); field2.setAccessible(true); System.out.println(field2.get(obj2)); } } // 获取匿名内部类实例 Field field = clazz.getDeclaredField("r"); field.setAccessible(true); Runnable r = (Runnable) field.get(container); r.run(); }
输出 函数
InnerA InnerB Method run of Runnable r
一、因为成员内部类对象的建立依赖于外部类对象,持有指向外部类对象的引用。因此在反射构形成员内部类的时候必定要经过获取 构造器再调用构造器的newInstance方法,其中必需要传入外部类的Class和实例。对于私有构造器,须要使用 getDeclaredConstructor方法获取并使用setAccessible(true)来设置为能够获取的。 二、静态内部类不持有外部类的引用,因此当其提供了无参显式的构造器的时候,能够直接在调用其class的newInstance()方法得到 实例。若是构造器为private的则处理同1中。若是没有提供显式的的无参构造器,只提供了有参构造器,处理也同1中。 三、若是内部类没有提供显式的构造器,则经过上面提到的方法构造内部类对象会抛出java.lang.IllegalAccessException错误。 即要经过上面提到的方法使用反射机制建立内部类对象,内部类必定要提供显式的构造函数!