java之反射Reflect

1.Class类的使用

(1)java中普通的数据类型类和静态的成员不属于对象。

(2)类也是对象,是java.lang.Class类的实例对象。

(3)Class类本身是无法new自身的。因为可以从源码看到:

         Class类本身的构造方法是一个私有的构造方法,只有java虚拟机可以来调用。

(4)Class类的使用代码: 

package function.reflect;

/**
 * Class类的使用
 *
 * @author kimtian
 */
public class ClassUsed {
    public static void main(String[] args) {
        //Student 对象的实例
        Student student1 = new Student();
        //Student这个类也是一个实例对象,是Class类的实例对象
        //任意一个类都是Class的实例对象,这个实例对象有三种表示方式

        //第一种表示方式-->任何一个类都有一个隐含的静态成员变量class
        Class c1 = Student.class;
        System.out.println(c1);

        //第二种表达方式  已经知道该类的对象,通过getClass方法调用
        Class c2 = student1.getClass();
        //第三种表达方式
        Class c3 = null;
        try {
            c3 = Class.forName("function.reflect.Student");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println(c2 == c3);
        /**
         * c1,c2表示了Student类的类类型(ClassType)
         * 万事万物皆对象
         * 类也是对象,是Class类的实例对象
         * 这个对象我们称为该类的类类型
         */
        // 不管c1 or c2 都代表了foo类的类类型,一个类只可能是Class类的一个实例对象
        System.out.println(c1 == c2);

        //我们完全可以通过类的类类型创建该类的实例对象。-->通过c1 or c2 or c3创建Student的实例
        Student student2 = null;
        try {
            //需要有无参数的构造方法,否则会报错
            student2 = (Student) c1.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

class Student {
}

2.动态加载类

(1)从上面可以看到   Class.forName("类的全称")    可以用来创建类的实例。

         c1.newInstance();不仅表示了类的类类型,还代表了动态加载类;

         编译时刻加载类是静态加载类、运行时刻加载类是动态加载类,我们在做一些通过功能方法的时候最好使用动态加载类。

(2)静态加载类的实现:

         由于使用的静态加载类,如果我们没有Office类,那么在编译Office类的时候就会出错。     

         如果有一个类似于Word、Excel这样的类出错,全部其他的功能都使用不了。

package function.reflect;

/**
 * 如果有一个出问题,全部其他的功能也都使用不了
 * 每次增加新功能,要修改基础代码
 *
 * @author kimtian
 */
public class Office {
    public static void main(String[] args) {
        if ("Word".equals(args[0])) {
            //new创建对象是静态加载类,在编译时刻就需要加载所有可能使用到的类。
            //只想在运行哪个时候加载哪个,就要使用动态加载类
            Word word = new Word();
            word.start();
        }
        if ("Excel".equals(args[0])) {
            Excel excel = new Excel();
            excel.start();
        }
    }
}

(3)动态加载类的实现:

          使用动态加载类,如果要使用Excel,但是没有Excel类,则只在运行的时候才会报错。但不会影响其他的,如Word的使用。

          我们给定一个OfficeAble的通用接口,使Word、Excel等都实现该接口,可扩展性好,新增类似其他的功能时,只需要增加新的代码实现OfficeAble通用接口。不用重新修改编译这个功能基础类。

package function.reflect;

/**
 * 如果需要加其他OfficeAble的具体实现,也不需要重新修改编译这个类
 *
 * @author kimtian
 */
public class OffiiceBetter {
    public static void main(String[] args) {
        try {
            //动态加载类,在运行时刻加载
            Class c = Class.forName(args[0]);

            //通过类类型,创建该类对象
            OfficeAble oa = (OfficeAble) c.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

猜你喜欢

转载自blog.csdn.net/third_/article/details/86471715