假如初识java或者只是玩一个小project,可能觉的反射用处不大,毕竟没有可用之处。但随着project越来越大,那反射就解决了好多key problems。首先我觉的反射这个名字太直白了,直接将reflect直译过来,我觉得应该叫内审或者自我剖析比较好,因为毕竟目的是要去了解一个类内部的一些属性或者方法嘛。
先举个栗子:
假如我的application需要和客户端交互(也是我碰到的真实栗子),客户的request里可能有各种各样的对我程序内交易类的访问,可能访问程序的模块A、模块B……..按照像我一样的小菜来说,可能首先想到的是:哦,把各种访问的可能性都考虑进来吧,于是:
switch(case){
case A :
doA();
break;
case B :
doB();
break;
case C :
doB();
break;
case D :
doB();
break;
...
.....
}
我承认假如我不接触反射我会这样去做。
回过头来分析一下:这个不确定性就是不知道客户会访问哪个模块,即无法在编译期就确定,那么一个思路就是:好吧,那就交给运行期去确定用户访问模块吧。我们知道:当new一个新对象时首先先将类信息加载到方法区(假如首次加载)然后再将类的成员变量在堆内存上分配空间(这里不懂得建议去看一下thinking in java喽),所以反射的话也是遵循这个思路:
Class.forName(request.getModule())——–forName()这个静态方法意思是根据后边的String参数即类名,将其new一个class对象,注意得到的是一个class对象,而不是实例哈,此时就可以对该对象调用一系列方法,如getMethods()、getConstructors()等等来获取该类的方法和构造器等等(因为这些都属于类的常量了,都是贮存在方法区不变的,不懂得看Tinking in java撒),当然也可以根据该类对象去new一个实例了,像我的业务就用到了newInstance(),于是乎,上边的switch就完全可以改成:
Class.forName(Request.getModule()).newInstance();
即根据用户request里的访问模块需求来new出模块实例
后续操作当然就是根据new出的实例去进行一系列方法调用…..操作了
这样是不是方便了很多?
最后给大家一个有趣的东东:假如忘记了一个jdk某类的一些信息(有哪些方法了)而又不想去查API文档,那就用反射吧:
package jsoup;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class Reflect {
public static void main(String[] args){
if(args.length<0){
System.exit(0);
}
if(args.length==1){
try {
Class obj = Class.forName(args[0]);
System.out.println("类名称为:" + obj.getName());
Method[] method = obj.getMethods();
for(Method m : method)
System.out.println("类内的方法有:"+ m);
Constructor[] con = obj.getConstructors();
for(Constructor c : con)
System.out.println("类的构造器为:" + c);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
在Eclipse运行的时候将arguments改成你需要查询的类的名称,注意是全称哦,for example:java.lang.String
或者在本地编译—运行 javac Reflect.java——-java Reflect java.lang.String