Java 框架技术基础---反射

Class 类的使用

在 Java 面向对象的世界里,万事万物皆对象!

  • 但是注意 Java 语言中,静态成员、普通数据类型都不是对象(封装类弥补了普通数据类型的不足)
  • 我们所编写的每一个类都是对象,类是 java.lang.Class 类的实例对象。 There is a class named Class 即这里有一个名称为 Class 的类,我们所写的每一个对象所属的类都是它的实例

Class 类的实例对象如何获取?

有以下代码中的三种方式:

package com.fy.reflect;

public class Test01 {

    public static void main(String[] args) throws ClassNotFoundException {
        // 类  A 的实例对象如何表示
        A a = new A();
        /* 类 A 也是 Class 类一个实例对象,因为任何一个类都是  Class 类的实例对象,
         * 官网称之为类类型,有如下三种表示方法
        */
        // 第一种表示方法:任何一个类都有一个隐藏的静态成员方法去获取 Class 实例
        Class c1 = A.class;
        // 第二种表示方法:利用某一个类的对象的  getClass()方法
        Class c2 = a.getClass();
        // Class 动态加载一个类
        Class c3 = Class.forName("com.fy.reflect.A");
        
        // 一个类只可能是 Class 类的一个实例对象,所以下面的输出都为 true
        System.out.println(c1 == c2); //输出  true
        System.out.println(c1 == c3); //输出  true
    }
}
class A{
    
}

如何理解动态加载类?

Class.forName("类的全称")

  • 不仅表示了类的类类型,还代表了动态加载类
  • 一定区分编译和运行

如何理解编译时刻加载类是静态加载类,运行时刻加载类是动态加载类

举个例子,我们 Java 开发者一般选择的 IDE 工具都是 Eclipse 或者 MyEclipse,比如以下代码,我创建了 Eclipse,没创建 MyEclipse 类,书写代码时就会出现错误(即编译出错),导致程序无法运行。也就是即使有了 Eclipse,没有 MyElicpse 也不能开发。但我们实际开发中,只有一个 IDE 工具给我们就能进行开发,不管有没有另外一个。再联想下,某个项目中有几十个功能,若是某个功能有问题其他功能就不能使用么?显然不合理。

public class JavaIDE {

    public static void main(String[] args) {
        //new 是静态加载类,在编译时都会加载所用到的类
        Eclipse e = new Eclipse();
        e.coding();
        MyEclipse m = new MyEclipse();
        m.coding();
    }
}
class Eclipse {
    public static void coding() {
        System.out.println("This is Eclipse");
    }
}

因此我们想到,用到某个功能就去加载某个类,即动态加载类。
为了更好的演示效果,希望大家在这里用文本编辑器编写代码,在 cmd 中利用 javac 命令编译、 java 命令运行代码

public class JavaIDE {

    public static void main(String[] args) throws Exception {
        // 动态加载,在运行时加载类
        Class c = Class.forName(args[0]);
        // 通过类类型,创建该对象
        IdeAble ia = (IdeAble)c.newInstance();
        ia.coding();
    }
}

在这里,我们通过类类型创建对象时,传统理念是

Eclipse e = (Eclipse)c.newInstance();

但是当我们需要的工具是 MyEclipse 时,这样则不满足功能要求。因此选择一个标准接口,所有功能类都去实现它,创建对象时只需创建接口对象就行。

这样需要什么功能,就去加载某个功能类就行。

interface IdeAble{
    public void coding();
}
class Eclipse implements IdeAble{
    public void coding() {
        System.out.println("This is Eclipse");
    }
}
class MyEclipse implements IdeAble{
    public void coding() {
        System.out.println("This is MyEclipse");
    }
}

再在cmd下,编译 JavaIDE 和 Eclipse,在运行。

当我们需要使用 Eclipse 功能时再去编写相应的代码,只要满足 IdeAble 接口标准就行,再运行即可


Java 框架技术基础---反射_第1张图片

方法的反射

    //获取类的所有方法
    public static void getMethods(Object obj) {
        Class c = obj.getClass();
        // 获取类所有的方法,包括从父类继承而来的
        Method[] methods = c.getMethods();
        for (Method method : methods) {
            // 获取方法的返回类类型
            Class returnType = method.getReturnType();
            System.out.print(returnType.getName() + " ");
            // 获取方法的名称
            System.out.print(method.getName() + "(");
            // 获取参数类型,得到的是参数列表的类型的类类型
            Class[] paramTypes = method.getParameterTypes();
            int i = 0;
            for (Class class1 : paramTypes) {
                if (i == paramTypes.length - 1) {
                    System.out.print(class1.getName());
                } else {
                    System.out.print(class1.getName() + ",");
                }
                i++;
            }
            System.out.println(")");
        }
      }

成员变量的反射

//获取类的所有成员属性
    public static void getField(Object obj) {
        Class c = obj.getClass();
        Field[] fields = c.getFields();
        for (Field field : fields) {
            System.out.println(field.getName());
        }
    }

构造函数的反射

//获取类的所有构造方法
    public static void getConstructor(Object obj) {
        Class c = obj.getClass();
        Constructor[] constructors= c.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.print(constructor.getName()+" (");
            Class[] conParams= constructor.getParameterTypes();
            int i=0;
            for (Class class1 : conParams) {
                if (i == conParams.length-1) {
                    System.out.print(class1.getName());
                    
                }else{
                    System.out.print(class1.getName()+",");
                }
                i++;
            }
            System.out.println(")");
        }
    }

Java类加载机制

你可能感兴趣的:(Java 框架技术基础---反射)