JavaSE(十)-反射

目录:

 

  •     反射是什么?
  •     从Class说起
  •     Class有什么用
  •     动态加载

前言:    这里只讲简单的语法, 不讲应用, 帮助理解JDBC的加载驱动, 以及明白框架原理, 如果想设计框架还要进一步学习. 

正文:

    1.    反射 Reflectoin
            反射机制是Java的一个非常重要的机制。一些著名的应用框架都使用了此机制。
        例如,
            struts, spring, hibernate
            android app的界面设计器 …

        在设计应用框架时一般都要使用反射,它是Java的一个非常优越的特性。

 

    2.    从Class说起
            java.lang.Class
            它是Java语法的一个基础类,用于描述一个class对象。
            在文件系统中,class以文件的形式存在 Student.class
            在运行时的JVM中,该*.class文件被加载到内存中成为一个对象,对象的类型就是java.lang.Class

        例如,
        Class cls = Student.class;
        System.out.println("Name: " + cls.getName());
        其中,cls这个对象就是这个Class的描述。
        再例如,
        Student obj = new Student();
        Class cls = obj.getClass();

        其中,obj是一个对象,obj.getClass()则是获取它的Class描述。


    3.    Class有什么用
        用于判断一个运行时对象的类型
  

      public static void test1(Object obj)
        {
            Class cls = Student.class;
            if(cls.isInstance(obj))
            {
            }
        }
        其中,cls.Instance(obj)意思是判断obj是否为my.Student的一个实例。


        另一种写法,也可以判断一个运行时对象的类型
        public static void test2(Object obj)
        {
            String clsName = obj.getClass().getName();
            if(clsName.equals("my.Student"))
            {
            }
        }

        其中,obj.getClass()可以得到对象obj的具体类型

小结:

 

  1.     可以通过两种方式创建Class,   类名.class 或  对象.getClass   
  2.     Class中有这个类中的所有信息, 属性名, 方法名, 参数, 异常, 父类名等.
  3.     Class中还要一些内置方法, 例如isInstance(), getName(), 需要查看文档了解. 

应用展示

让一个对Student对象可以与String和Integer进行比较。

public boolean equals(Object obj)
{
	// 与一个String对象比较
	if(String.class.isInstance(obj))
	{
		String other = (String)obj;
		return other.equals(this.name);
	}
	// 与一个Integer对象比较
	if(Integer.class.isInstance(obj))
	{
		Integer other = (Integer)obj;
		return this.id == other;
	}
	return false;
}

    4.    Reflection
    给定一个*.class文件中,我们可以得到以下信息:
    类名 (含package路径)
    函数 (名称,参数类型,返回值)
    域 (名称,类型)
    实现的接口 (interfaces)
    … …
    使用java.lang.reflect.*下的类来实现。。。
    注意:不需要源文件,只需要*.class文件


    动态加载一个*.class文件到内存:

    // 加载my/Student.class
    Class cls = Class.forName("my.Student");
    // 获取函数列表
    Method[] methods = cls.getMethods();
    // 获取成员变量列表
    Field[] fields = cls.getFields();


    也就是说,虽然我们不知道Student类的代码,但是这个class文件本身可以反映(reflect)出这些信息。。。

    结论:通过Reflection机制,我们可以直接从class文件反推出它有哪个成员变量、有哪些函数。

    例1 遍历Method
    已经函数名,找到对象的 Method(如何获取函数名?  看使用文档, 遍历函数列表, 打电话问设计者)

    Class cls = Class.forname("my.Student");
    String methodName = "setId";
    // 获取所有Method列表,顺序比对
    Method[] methods = cls.getMethods();
    for(Method m : methods)
    {
        if(m.getName().equals(methodName))
        {
            break;
        }
    }


    例2 查找Method
    已经函数名,参数列表,寻找Method

    Class cls = Class.forname("my.Student");
    String methodName = "setId";
    Class[] parameterTypes = { int.class };
    Method m = cls.getMethod(methodName,parameterTypes);


    例3 Reflection的运用

    // 创建一个实例, 要求有一个不带参数的构造函数
    Object obj = cls.newInstance();
    // 找到method
    Class[] parameterTypes = { int.class };
    Method m1 = cls.getMethod("setId",parameterTypes);
    // 调用method
    Object[] paramters = { 123 };

    m1.invoke(obj, paramters);

        更多细节 Class Loader
        Class.forName(…) 可以加载一个class文件。(所以创建Class类有三种方法了)
        (1)由谁负责加载?
                 由Class Loader负责加载,具体地讲,JVM提供了一个内置的 bootstrap class loader。
        (2)从哪里加载?

        从classpath下寻找class,以及该class里面import的class

 

        小结
        1.Reflection: 从*.class文件中,可以reflect得到它的描述信息:类名,函数名等
        2.通过Class,可以newInstance()创建一个实例instance
        3.通过Class,可以找到它的某个Method,进而就可以调用这个函数。(有函数名, 有实例了不就可以调用了??)

        4.需要知道Class Loader的存在及其作用

    如果不是为了设计框架, 学这么多应该也就够了, 毕竟普通的开发一般不会使用到反射, 现在主流的框架也是使用反射机制, 学习框架的时候可以思考一下, 自己如何通过反射设计一个这样的框架来. 

你可能感兴趣的:(javaSE,反射,JavaSE)