一、定义

反射(reflection)是java的特征之一,它允许允许中的Java程序获取自身的信息,并且可以操作累或对象的内部属性。

二、基本运用

反射可以用于判断任意对象所属的类,获得 Class 对象,构造任意一个对象以及调用一个对象。反射相关的类一般都在 java.lang.relfect 包里。

1. 获取Class对象

public class Demo01 {
    public static void main(String[] args) throws Exception{
        String str = new String();
        // 1.通过对象的getClass方法获得
        Class strClass = str.getClass();
        System.out.println(strClass.getName());

        // 2.通过class属性获得
        // 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
        Class strClass2 = String.class;
        System.out.println(strClass2.getName());
        System.out.println(strClass2 == strClass);

        // 3.使用Class类的forName静态方法
        // 注意此字符串必须是真实路径,就是带包名的类路径,包名.类名
        try{
            Class strClass3 = Class.forName("java.lang.String");
            System.out.println(strClass3 == strClass2);
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println(strClass.isInstance("test"));

        System.out.println(strClass instanceof Object);

    }

}

// 结果:
java.lang.String
java.lang.String
true
true
true
true

说明

获取Class对象的三种方法:

  • 调用某个对象的getClass方法;

  • 直接获取某个类型的class属性:

  • 使用Class类的forName静态方法。

注意:在运行期间,一个类,只有一个Class对象产生。

2. 判断是否为某个类的实例

一般使用instanceof关键字判断是否为某个类的实例,也可以使用反射中Class对象的isInstance()方法(native方法)判断是否为某个类的实例,

System.out.println(strClass.isInstance("test"));
System.out.println(strClass instanceof Object);

3. 创建实例

// 创建实例
// 1. newInstance()
String string = (String) strClass.newInstance();
System.out.println(string);

// 2. 先通过Class对象获取指定Constructor对象,再调用Constructor对象的newInstance()方法来创建实例。
// 这种方法可以指定构造器的实例。
Constructor constructor = strClass.getConstructor(String.class);
String string2 = (String) constructor.newInstance("23333");
System.out.println(string2);

说明

  • 使用Class对象的newInstance()方法来创建Class对象对应类的实例。
  • 先通过Class对象获取指定Constructor对象,再调用Constructor对象的newInstance()方法来创建实例。

4. 获取方法

public class Demo02 {

    public static void main(String[] args) throws Exception {
        Class<?> clazz = MethodClass.class;

        // 创建类实例
        Object obj = clazz.newInstance();


        // 获取所有共有方法, 包括继承
        Method[] methods = clazz.getMethods();
        for (Method m : methods) {
            System.out.println(m);
        }

        System.out.println("----------");
        // 获取所有私有方法,不包括继承
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method dm : declaredMethods) {
            System.out.println(dm);
        }

        System.out.println("----------");
        // 获取指定方法
        Method add = clazz.getMethod("add", int.class, int.class);
        // 调用方法 (要先创建实例对象)
        Object r = add.invoke(obj, 1, 1);
        System.out.println(r);
        System.out.println(add);

        System.out.println("----------");
        // 获取指定方法(私有)
        Method sub = clazz.getDeclaredMethod("sub", int.class, int.class);
        sub.setAccessible(true);
        Object result = sub.invoke(obj,12, 2);
        System.out.println(result);

    }


}

class MethodClass {
    public int add(int a, int b) {
        return a + b;
    }
    private int sub(int a, int b){
        return a - b;
    }
}

说明

  • getDeclaredMethods()方法返回类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。

  • getDeclaredMethod()方法可以获取特定的私有方法。

  • getMethods()方法返回某个类的所有公用(public)方法,包括其继承类的公用方法。

  • getMethod()方法返回一个特定的方法,其中第一个参数为方法名称,后面的参数为方法的参数对应Class的对象。