java 运行时类型识别(RTTI) - 2 - 反射(五)

2014-11-24 08:56:44 · 作者: · 浏览: 4
果如下
[java]
private java.lang.String TAG
StaticInner
StaticInnerTAG
TAG
StaticInner只声明了一个变量,名字为TAG,类型为String
即使是private变量,设置setAccessible(true)之后也能改变其值
普通内部类的反射和上面类似

最后说下匿名内部类
匿名内部类的作用是仅仅使用一次,所以也没有必要进行反射,实际上也很难进行反射
例子中有两个匿名内部类
[java]
TestInterface ti = new TestInterface() {
public String test() {
return "this is ti";
}
};

public String toString(){
System.out.println("Outer toString");
return new TestInterface() {
public String test() {
return "this is a test!";
}
}.test();
}
在bin目录下发现有Outer$1.class和Outer$2.class

getDeclaredClasses发现也没有匿名内部类的信息

[java]
try {
Class outer = Outer.class;
Class< >[] classes = outer.getDeclaredClasses();
for (Class< > clazz : classes) {
System.out.println(clazz.getName());
}
}catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
结果
[java]
reflect.Outer$Inner
reflect.Outer$StaticInner
reflect.Outer$TestInterface
只有这三个,包括一个接口
如果非要对匿名内部类进行反射,也不是不可能
下面演示如何反射一个匿名内部类,仅仅是演示,没有任何意义,也不推荐这么做
我们以上面的toString方法里面的内部类做例子
[java]
try {
Class< > clazz = Class.forName("reflect.Outer$2");
Constructor< >[] constructors = clazz.getDeclaredConstructors();
constructors[0].setAccessible(true);
Class< >[] types = constructors[0].getParameterTypes();
for (Class< > type : types) {
System.out.println("Parameter Types:" + type.getName());
}
TestInterface testInterface = (TestInterface) constructors[0].newInstance(new Outer(""));
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
Class< >[] parameterTypes = method.getParameterTypes();
System.out.println(method.getName() + "(" + arrayToString(parameterTypes) + ")");
}
Method method = clazz.getDeclaredMethod("test");
String string = (String)method.invoke(testInterface);
System.out.println(string);
}catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
结果如下
[java]
Parameter Types:reflect.Outer
Testing..
Outer
test()
this is a test!
下面看看代码都做了什么,依次说明
首先获取Outer$2的Class
然后获取其构造器,查看所需要的参数,我们发现内部匿名类也需要一个外部类的支持
然后我们newInstance生成实例,声明为一个接口,由于要传入外部类,这里我们直接new一个,所以会初始化外部类,打印第2,3句
接下来查看内部类的方法,找到test(),这是第4句打印的结果
最后用实例化好的内部匿名类执行这个方法,所以打印出了最后一句

执行第一个匿名内部类的方法代码简单些,同样不推荐这么做
[java]
try {
Class clazz = Outer.class;
Outer o = new Outer("");
//System.out.println(o.ti.test());
Field field = clazz.getDeclaredField("ti");
TestInterface testInterface = (TestInterface) field.get(o);
System.out.println(testInterface.test());
}catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
为了演示反射,这里没有使用System.out.pr