Java 中的反射

反射的概念

根据某个对象来获取该对象所对应的类的完整信息。

反射的功能

  1. 可以判断运行时对象所属的类;
  2. 可以判断运行时对象所包含的成员变量和方法。

Java 反射机制中的类

java.lang.Class
java.lang.reflect.Constructor
java.lang.reflect.Field
java.lang.reflect.Method
java.lang.reflect.Modifier

类类型

在 Java 中,万物皆对象,Object 类是所有类的父类,所有类的实例化对象都是 Class 类的对象,Class 类的对象称为类类型。

获取一个类的类类型的方法

首先,我们有一个 Person 类,如下:

package reflecttest;

public class Person {
    
    // 定义 private 修饰的成员变量
    private String name;
    private int age;
    
    // 定义一个无参构造方法
    public Person() {
        
    }

    // 定义一个 public 修饰的带参数构造方法
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    // get set 方法
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    // 重写 toString() 方法
    @Override
    public String toString() {
        return name + ", " + age;
    }
    
}

1. 对象.getClass()

任何一个类都继承了 Object 类,因此也继承了 getClass() 方法,通过该类的对象调用 getClass() 方法可以得到该类的类类型。

public class Test01 {
    
    public static void main(String[] args) {

        Person p = new Person();
        Class c1 = p.getClass();
        // 取得类名
        System.out.println(c1);
        // 取得包名
        System.out.println(c1.getName());

    }
    
}

运行结果:


2. 类名.class

每个类中都隐含了一个静态属性 class,通过 类名.class,也可以获得该类的类类型。

public class Test01 {
    
    public static void main(String[] args) {
        
        Class c2 = Person.class;
        // 取得类名
        System.out.println(c2);
        // 取得包名
        System.out.println(c2.getName());
        
    }
    
}

运行结果:


3. Class.forName

通过动态加载类,Class.forName(“类名的全称(包含包名)”),Class.forName 必须抛出异常或对异常进行捕获处理。

public class Test01 {
    
    public static void main(String[] args) {
        
        try {
            Class c3 = Class.forName("reflecttest.Person");
            // 取得类名
            System.out.println(c3);
            // 取得包名
            System.out.println(c3.getName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        
    }
    
}

运行结果:


注: 静态加载,在编译时加载的类称为静态加载类;动态加载,在运行时加载的类称为动态加载类。

通过一个类的类类型获取该类的详细信息

获得一个类的类类型后,可以创建该类对象,并且反射出该类中的方法和属性。

1. 通过类类型创建对象

public class Test02 {

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        
            Person p1 = new Person();
            Class c1 = p1.getClass();
            Person p2 = (Person) c1.newInstance();
            
            Class c2 = Person.class;
            Person p3 = (Person) c2.newInstance();
            
            Class c3 = Class.forName("reflecttest.Person");
            Person p4 = (Person) c3.newInstance();
            
            // 得到类类型所代表的类名的全称,包含包名
            System.out.println(c3.getName());
            // 得到类类型所代表的类名,不包含类名
            System.out.println(c3.getSimpleName());
        
    }

}

运行结果:


注意: 通过类类型创建对象时,该类必须要有无参的构造方法。

2. 通过类类型反射出该类中所有的属性

在 Java 中,万物皆对象,属性也是对象,它是 Feild 类的对象。

方法 描述
getFeilds() 获得该类的所有公有属性,包括该类从父类中继承的
getDeclaredFields() 获得所有该类自己声明的属性,不论访问权限
getField(name) 根据给定属性名得到公有的属性的类

通过类类型反射出该类中所有的方法

在 Java 中,万物皆对象,方法也是对象,它是 Method 类的对象。

方法 描述
getMethods() 获得该类的所有 public 方法,包括从父类中继承的和从接口实现的方法
getDeclaredMethods() 获得所有该类自己声明的方法,不论访问权限
getMethod(Sting name, Class... parameterTypes) 根据指定方法和参数列表得到相应的公有方法,包括包括从父类中继承的和从接口实现的方法
getDeclaredMethod(Sting name, Class... parameterTypes) 根据指定方法和参数列表得到该类自己的公有方法

通过类类型反射出该类的所有构造方法

在 Java 中,万物皆对象,构造方法也是对象,它是 Constructor 类的对象。

方法 描述
getDeclaredConstructors() 得到该类的全部构造方法,不论访问权限
getConstructors() 得到该类的公有构造方法

参考资料:

  • JAVA中的反射机制 - 刘佳翰
  • java中的反射总结 - Nerxious

你可能感兴趣的:(Java 中的反射)