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

2014-11-24 08:56:44 · 作者: · 浏览: 1
ngBuilder.append(",");
}
if(classes.length > 0){
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
}
return stringBuilder.toString();
}
打印结果
[java]
Testing..
reflect.Outer(java.lang.String)
Outer
Outer toString
this is a test!

下面简单分析下
[java]
Class< > outer = Class.forName("reflect.Outer");
//outer = Outer.class;
我们对类reflect.Outer进行反射,这里使用Outer.class也可以获得Class对象
之前说过使用类字面量不会初始化该类,而Class.forName则会初始化 ,当使用Outer.class时候log如下
[java]
reflect.Outer(java.lang.String)
Testing..
Outer
Outer toString
this is a test!
顺序改变了,打印的时候Testing..实际是下面这句触发的
[java]
Outer outerInstance = (Outer) outerConstructor.newInstance("a outer");
这时候加载Outer这个类,然后进行初始化

接下来我们查看了Outer的所有构造器Constructor,并打印出所需要的参数(与普通方法区别开来)
构造器只有一个,参数是String
如何执行这个带有String作为参数的构造器来返回一个Outer实例
[java]
Constructor< > outerConstructor = outer.getConstructor(String.class);
Outer outerInstance = (Outer) outerConstructor.newInstance("a outer");
System.out.println(outerInstance);
我们先取得我们需要的Constructor,然后,Constructor提供了newInstance方法,这样就可以获得Outer实例
最后打印实例,调用了toString函数
如果你尝试调用
[java]
outer.newInstance();
则会看到如下异常
java.lang.InstantiationException: reflect.Outer
at java.lang.Class.newInstance0(Class.java:357)
at java.lang.Class.newInstance(Class.java:325)
at reflect.Test.main(Test.java:30)

这是因为Outer没有提供默认构造器
在获得Constructor时其实是有下面两个选择的,至于区别,我们放在Method里说
[java]
outer.getConstructors();
outer.getDeclaredConstructors()
现在看看如何获得类的方法,顺便看看Declared的作用
不如直接打印出来,这样比较直观
[java]
Method[] methods = outer.getMethods();
for (Method method : methods) {
Class< >[] types = method.getParameterTypes();
System.out.println(method.getReturnType().getName() + " " + outer.getName() + "." + method.getName() + "(" + arrayToString(types) + ")");
}
System.out.println("--------------------------------------");
methods = outer.getDeclaredMethods();
for (Method method : methods) {
Class< >[] types = method.getParameterTypes();
System.out.println(method.getReturnType().getName() + " " + outer.getName() + "." + method.getName() + "(" + arrayToString(types) + ")");
}Class< > outer = Outer.class;
结果如下
[java]
void reflect.Outer.staticMethod()
java.lang.String reflect.Outer.toString()
void reflect.Outer.wait(long)
void reflect.Outer.wait()
void reflect.Outer.wait(long,int)
boolean reflect.Outer.equals(java.lang.Object)
int reflect.Outer.hashCode()
java.lang.Class reflect.Outer.getClass()
void reflect.Outer.notify()
void reflect.Outer.notifyAll()
--------------------------------------
void reflect.Outer.privateMethod()
void reflect.Outer.protectedMethod()
void reflect.Outer.packageMethod()
void reflect.Outer.staticMethod()
java.lang.String reflect.Outer.toString()
调用getMethods时,Outer的方法只打印出了toString,其余结果均为父类Object的公有方法
调用getDeclaredMethods时,则只打印出在Outer中声明定义的方法
他们均打印出了公共的静态方法
所有带Declared和不带Declared的成对的方法都和上面的类似

如何利用反射执行一个方法,下面以void reflect.Outer.privateMethod()为例
[java]
Method method = outer.getDeclaredMethod("privateMethod");
method.setAccessible(true);
method.invoke(outerInstance, (Object[])null);
method.setAccessible(false);
首先privateMethod是私有方法,所以为了能得到对应的Method对象,我们需要调用getDeclaredMethod

为了能访问私有方法,我们需要进行setAccessible(true)的设置
然后需要有个对象来执行,我们选择刚才的outerInstanc