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

2014-11-24 08:56:44 · 作者: · 浏览: 2
e
这时控制台输出
[java]
privateMethod
干完活后,恢复其设置setAccessible(false)
下面是静态方法的执行
[java]
Method method = outer.getDeclaredMethod("staticMethod");
method.setAccessible(true);
method.invoke(Outer.class, (Object[])null);
method.setAccessible(false);
ps:使用method.invoke(outerInstance, (Object[])null);也能执行,但是不该这样

内部类
isInterface,Field,isAccessible,setAccessible,getModifiers,Modifier.toString()
下面看看内部类的反射
[java]
Class< >[] classes = outer.getDeclaredClasses();
for (Class< > clazz : classes) {
if(clazz.isInterface()){
System.out.println("interface : " + clazz.getName());
}else{
System.out.println("class : " + clazz.getName());
}
}
输出
[java]
class : reflect.Outer$Inner
class : reflect.Outer$StaticInner
interface : reflect.Outer$TestInterface
看来反射提供的api功能还是很全的

下面是如何反射静态内部类
[java]
try {
Class staticInner = StaticInner.class;
StaticInner staticInnerInstance = staticInner.newInstance();
}catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
也可以使用Class.forName方式,如果StaticInner是不可见的,那么上面的代码则无法编译,下面看看Class.forName
[java]
try {
Class staticInner = (Class) Class.forName("reflect.Outer.StaticInner");
StaticInner staticInnerInstance = staticInner.newInstance();
}catch (SecurityException e) {
e.printStackTrace();

} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
如果你和上面的写法一样,那么很不幸,运行时会得到如下错误
java.lang.ClassNotFoundException: reflect.Outer.StaticInner
at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:186)
at reflect.Test.main(Test.java:11)

我们去bin目录下可以发现这样的文件Outer$StaticInner.class
反射代码只需做如下改动
[java]
Class staticInner = (Class) Class.forName("reflect.Outer$StaticInner");
.变成了$
这里newInstance之所以能执行,是因为StaticInner有默认构造器
下面看看StaticInner中生命了哪些变量
[java]
Class staticInner = StaticInner.class;
Field[] fields = staticInner.getDeclaredFields();
for (Field field : fields) {
Class< > type = field.getType();
field.setAccessible(true);
System.out.println(Modifier.toString(field.getModifiers()) + " " + type.getName() + " " + field.getName());
}

StaticInner StaticInnerInstance = staticInner.newInstance();
Field field = staticInner.getDeclaredField("TAG");
boolean accessible = field.isAccessible();
if(!accessible){
field.setAccessible(true);
}
System.out.println(field.get(StaticInnerInstance));
field.set(StaticInnerInstance, "TAG");
System.out.println(field.get(StaticInnerInstance));
if(!accessible){
field.setAccessible(false);
}