第一次感受DI(Dependency Injection) & java.lang.reflect.* 学习
糊涂鬼 2005-05-12
说是说感受一下这个东西DI(也可以说是IoC-(Inversion of Control)吧),其实我对它的认识只有一点点,甚至说我今天写的这个程序有没有用到它我都不敢肯定,只是我感觉我是用到了的。好了,废话我不多说了,先把两个程序贴出来,浏览一下,别细读。
Program 1(without DI):Program 2(with DI):package cn.liltos.reflect;
import java.lang.reflect.*;
public class GetClassInfo_1 {
public static void main(String[] args) {
long start = System.currentTimeMillis();
String s = "cn.liltos.reflect.Beans";
getClassName(s);
getFields(s);
getConstructor(s);
getMethods(s);
System.out.println("}");
long end = System.currentTimeMillis();
long cost = end - start;
System.out.println("this program last : " + cost);
}
public static void getConstructor(String s) {
System.out.println("\n //构造方法");
Class c = getClass(s);
Constructor[] constructor = c.getConstructors();
printObjectArray(constructor);
}
public static void getMethods(String s) {
System.out.println("\n //成员方法\n");
Class c = getClass(s);
Method[] method = c.getDeclaredMethods();
printObjectArray(method);
}
public static void getFields(String s) {
System.out.println("{\n //成员变量");
Class c = getClass(s);
Field[] field = c.getFields();
printObjectArray(field);
}
public static void getClassName(String s) {
System.out.print("class ");
String className = getClass(s).getName();
System.out.println(className);
}
public static Class getClass(String s) {
Class c;
try {
c = Class.forName(s);
} catch(ClassNotFoundException ex) {
return null;
}
return c;
}
public static void printObjectArray(Object[] obj) {
for(int i = 0; i < obj.length; ++i) {
System.out.println(" " + obj[i]);
}
}
}package cn.liltos.reflect;
import java.lang.reflect.*;
public class GetClassInfo_2 {
public static void main(String[] args) {
long start = System.currentTimeMillis();
String s = "cn.liltos.reflect.Beans";
Class c = getClass(s);
getClassName(c);
getFields(c);
getConstructor(c);
getMethods(c);
System.out.println("}");
long end = System.currentTimeMillis();
long cost = end - start;
System.out.println("this program last : " + cost);
}
public static void getMethods(Class c) {
System.out.println("\n //成员方法");
Method[] method = c.getDeclaredMethods();
printObjectArray(method);
}
public static void getFields(Class c) {
System.out.println("{\n //成员变量");
Field[] field = c.getFields();
printObjectArray(field);
}
public static void getConstructor(Class c) {
System.out.println("\n //构造方法");
Constructor[] constructor = c.getConstructors();
printObjectArray(constructor);
}
public static void getClassName(Class c) {
System.out.print("class ");
System.out.println(c.getName());
}
public static Class getClass(String s) {
Class c;
try {
c = Class.forName(s);
} catch(ClassNotFoundException ex) {
return null;
}
return c;
}
public static void printObjectArray(Object[] obj) {
for(int i = 0; i < obj.length; ++i) {
System.out.println(" " + obj[i]);
}
}
}
这两个程序我把注释全部删除了,对于一个如此简单的程序,实在没有必要把注释都写出来,我想我的命名应该还是可以的,看方法名就可以知道方法是做什么的吧(:-),有点臭美,容忍一下)。
另外程序还涉及到一个叫‘cn.liltos.reflect.Beans’的类,看名字就知道啦,这个类里面无非也就是一些 field 和一些 method,再没有其它什么值得注意的东东了。
现在说一下这两个程序是用途,运用JAVA的反射机制,读取想查看的类(这里是cn.liltos.reflect.Beans)的一些细节,并将得到的结果打印在屏幕上。为了打印出来的东西具有一定的可读性,我在程序里便有了那些不美观的、一大堆的换行控制。同时,为了检查程序的执行时间,在 main() 的开始和结束都调用了 System.currentTimeMillis() 来确定时间。最后输出程序的执行时间。在程序里运用的反射的几个方法也比较简单。我晕,又说了一堆废话 :-(
两个程序的方法(均为 static),相同的有 void printObjectArray(Object[] obj)、Class getClass(String s)、void main(String[] args)。而其它的方法,只有名字是相同的,参数则不一样。第一个程序里其它的方法的参数都是 String s, 而后者则是以 Class c 为参数,这也是我认为后者采用的是 DI 的原因,方法体都是根据传入的参数所代表的类去寻找类的细节。
看一个JAVA程序的运行效率有多高,一般是看第一次运行的,这个观点不知道是否正确,因为如果JVM一次次地运行同一个程序的话,它会一次次的优化字节码,相信有很多朋友有这样的经验,编译同一个程序,第二次编译的时间会很明显地比第一次编译花的时间少。对于运行,同理可证。呵呵~~~~
那这上面的两个程序的效率到底差了多少呢?在第一次运行的时候,Program 1 花了 7000 多 Milliseconds ,而 Program 2 只花了 170 个单位。这个数字有点吓人会吗?反正我执行完第二个程序后看到的这个数字差时是被吓了一跳。不过在运行了将近十次以后,两个程序的时间差少了非常非常之多,只有 40 个单位的时间了。
40 Milliseconds,这个数字太不大了,呵呵,才40,只要我的机器配置再高一些,这点时间,压根就感觉不到,确实,一点都没错。但是——最讨厌看到一堆美好之词后面加这个词了——但是,这只是一个非常小的程序,非常非常小。如果现在运行的不是一个程序,而是一组、或是几个 package 的程序,那么这个时间就非常之可观了,不是么?
看到这里了,先打住,有一件事情我不敢确定,上面的程序有用到 DI 的思想吗?恳请高手指点一下,我实在是没什么自信。
相信有很多朋友对于那些高手们左口一个 IoC 右口一个 DI 一定感到很羡慕,羡慕人家知道那么多东西。如果到这里我上面的程序确实有用到 DI 的思想的话,那么,请允许我班门弄斧似滴说一下上面在什么地方用到了 DI 吧。
public static void getMethods(String s) {
System.out.println("\n //成员方法\n");
Class c = getClass(s);
Method[] method = c.getDeclaredMethods();
printObjectArray(method);
}
这一段程序,为了得到 s 代表的类的自己声明的方法,参数 String s 是类在 classpath 上的位置。进入方法体后,再用 Class c = getClass(s); 得到 Class 类的实例,然后调用 c.getDeclaredMethods() 得到这个实例自己声明的方法。
与之对应的另一个方法如下:
public static void getMethods(Class c) {
System.out.println("\n //成员方法");
Method[] method = c.getDeclaredMethods();
printObjectArray(method);
}
参数直接变成了 Class c,也就是说,直接把 Class 的实例注入方法,而不是在方法中再去寻找/创建。在这个小程序中,外在的好处只是处理时间减少了一点点,但是,将控制权从方法内部转移到外部,减少方法需要做的工作,便意味着一个提高。有一点是必须注意的尽量简化方法,让一个方法只做好自己本职的那份工作,是面向对象的一个很基本的原则,可以提高代码的复用率。虽然只是一个方法的重用,但养成一个好习惯会比较好一点。
本文地址:http://com.8s8s.com/it/it9895.htm