第一次感受DI & java.lang.reflect.* 学习

类别:Java 点击:0 评论:0 推荐:

                                      

           第一次感受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