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

                                      

           第一次感受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 的实例注入方法,而不是在方法中再去寻找/创建。在这个小程序中,外在的好处只是处理时间减少了一点点,但是,将控制权从方法内部转移到外部,减少方法需要做的工作,便意味着一个提高。有一点是必须注意的尽量简化方法,让一个方法只做好自己本职的那份工作,是面向对象的一个很基本的原则,可以提高代码的复用率。虽然只是一个方法的重用,但养成一个好习惯会比较好一点。

Java中,`java.lang.reflect.Type`和`java.lang.Class`是两个不同的类型,它们分别表示不同的概念。`java.lang.reflect.Type`表示Java中的类型,可以是基本类型、类、接口、数组、泛型等;而`java.lang.Class`表示类的定义,包括类的名称、方法、属性等信息。 如果需要将`java.lang.reflect.Type`转换为`java.lang.Class`,可以通过以下方式实现: ```java import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; public class TypeToClassDemo { public static void main(String[] args) { // 获取一个泛型类型 Type type = new TypeReference<String>() {}.getType(); // 将泛型类型转换为Class Class<?> clazz = getClass(type); System.out.println(clazz.getName()); // 输出: java.lang.String } public static Class<?> getClass(Type type) { if (type instanceof Class) { // 如果是Class类型,则直接返回 return (Class<?>) type; } else if (type instanceof ParameterizedType) { // 如果是ParameterizedType类型,则获取原始类型 ParameterizedType parameterizedType = (ParameterizedType) type; return (Class<?>) parameterizedType.getRawType(); } else { // 如果是其他类型,则抛出异常 throw new IllegalArgumentException("Unsupported type: " + type); } } // 定义一个泛型类型引用 private static abstract class TypeReference<T> { Type getType() { Type superClass = getClass().getGenericSuperclass(); if (superClass instanceof Class) { throw new IllegalArgumentException("Missing type parameter."); } ParameterizedType parameterized = (ParameterizedType) superClass; return parameterized.getActualTypeArguments()[0]; } } } ``` 在上面的代码中,我们首先定义了一个泛型类型`TypeReference<T>`,然后通过`getType()`方法获取泛型类型。接着,我们使用`getClass()`方法将泛型类型转换为`Class`类型。在`getClass()`方法中,我们判断了类型是否为`Class`和`ParameterizedType`,并分别进行了处理。最后,我们就成功地将`java.lang.reflect.Type`类型转换为了`java.lang.Class`类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值