反射

57 阅读3分钟

1.什么是反射

反射是指在程序运行时,对于任意一个类,都能知道这个类的所有属性和方法;对于任意一个对象,都能调用它的任意方法和属性。这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。

2.反射的作用

  • 获取类的名称、package信息、所有属性、方法、注解、类型、类加载器等
  • 获取任意对象的属性并且能够改变对象的属性
  • 调用对象的方法
  • 判断对象所属的类
  • 实例化类的对象
  • 在应用程序运行时,通过反射可以实现动态代理,动态的调用方法等

3.反射的使用

一个类由三部分组成,构造器 + 属性 +方法

示例代码使用的类

public class Person {

    private String name;

    private int age;

    private String address;

    public Person(){}

    public Person(String name){
        this.name = name;
    }

    public Person(String name, int age){
        this.name = name;
        this.age = age;
    }

    Person(String name, String address){
        this.name = name;
        this.address = address;
    }
    
    ... ... //省略get set
    
    public void eat(){
        System.out.println("person eat food ...");
    }

    public void sleep(){
        System.out.println("person sleep ...");
    }

    public String sleep(Integer time){
        System.out.println("person sleep " + time + "mins");
        return "person sleep " + time + "mins";
    }
}

(1)通过反射获取类的构造器

方法说明如下:

方法说明
Constructor<?>[] getConstructors()获取定义的public的构造器
Constructor getConstructor(Class<?>... parameterTypes)根据指定参数类型获取public构造器
Constructor<?>[] getDeclaredConstructors()获取定义的所有构造器
Constructor getDeclaredConstructor(Class<?>... parameterTypes)根据指定参数类型获取定义的构造器

示例代码如下:

//获取所有public的构造器
Constructor<?>[] constructors = personClazz.getConstructors();

//获取指定参数的public构造器 
Constructor<?> constructor1 = personClazz.getConstructor(String.class);

//获取所有定义的构造器
Constructor<?>[] declaredConstructors = personClazz.getDeclaredConstructors();

//获取指定参数定义的构造器
Constructor<?> declaredConstructor = personClazz.getDeclaredConstructor(String.class);

(2)通过反射获取类的属性

方法说明如下:

方法说明
Field[] getFields()获取所有public的属性
Field getField(String name)获取指定属性名的public的属性
Field[] getDeclaredFields()获取所有的属性
Field getDeclaredField(String name)获取指定属性名的属性

示例代码如下:

//获取所有public的属性
Field[] fields = personClazz.getFields();

//获取指定属性名的public属性
Field name1 = personClazz.getField("name");

//获取所有定义的属性
Field[] declaredFields = personClazz.getDeclaredFields();

//获取指定属性名的属性
Field name2 = personClazz.getDeclaredField("name");

此外,还可以设置属性的值,示例代码如下:

Constructor<?> constructor = personClazz.getConstructor(String.class); 
Object obj = constructor1.newInstance("zys");//实例化一个name为zys的对象 
Field nameField = personClazz.getDeclaredField("name"); 
field.setAccessible(true);//私有属性要设置可访问,否则无权限 
nameField.set(zys, "ds");//将对象的obj的name属性重新设置为ds

(3)通过反射获取类的方法

方法说明如下:

方法说明
Method[] getMethods()获取类的所有public的方法
Method getMethod(String name, Class<?>... parameterTypes)获取类的指定参数的public方法
Method[] getDeclaredMethods()获取类的所有方法
Method getDeclaredMethod(String name, Class<?>... parameterTypes)获取类的指定参数的方法

示例代码如下:

//获取类的所有public方法 
Method[] methods = personClazz.getMethods();

//根据方法名获取public方法
Method eat = personClazz.getMethod("eat"); 

//获取类的所有定义的方法
Method[] declaredMethods = personClazz.getDeclaredMethods();

//根据方法名获取方法
Method declaredMethod = personClazz.getDeclaredMethod("test");

此外,获取方法后,可以直接调用,示例代码如下:

Method[] methods = personClazz.getMethods();//获取类的所有public方法 

personClazz.getMethod("sleep", Integer.class);//根据方法名获取public方法 

Object invoke1 = sleep1.invoke(obj, 10);//直接调用方法

4.反射的原理

主要点就是类的加载时机。正常的应用程序代码,类的加载是程序中的hard code, 而反射是动态地去加载某个类,程序的耦合性较低。反射常见的使用就是动态代理。