快速了解Java反射

快速了解Java反射

相信大家都知道反射的重要性,每个类的对象都可以通过反射构造出来,反射可以获取类的所有属性、方法。注解离不开反射机制,设计模式里面的动态代理也是依靠反射进行的,很多优秀框架都是在反射机制下完成的。
概念、理论再多都不如代码实在(有不对的地方,欢迎指出,同样也欢迎内容补充)。

先写一个Person类

public class Person {

    private String name;
    public int age;

    public Person() {}

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

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

    public String getName() {
        System.out.println("获取姓名");
        return name;
    }

    private void setName(String name) {
    	System.out.println("姓名写入中...");
        this.name = name;
    }

    private void init(String name,int age){
    	System.out.println("进行初始化...");
        this.name = name;
        this.age = age;
    }

	@Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

一、获取Class对象的三种方式

1.对象调用getClass()方法

Class代表一个类,通过Class可以拿到对应类的属性及方法。

Person person = new Person();
Class<? extends Person> clazz = person.getClass();

2.对应类的静态属性class

Class<Person> clazz = Person.class;

3.调用Class类的静态方法forName(“详细路径”)

Class<?> clazz = Class.forName("com.***.demo.Person");

二、获取类的构造方法

Constructor代表构造方法

1、getDeclaredConstructors()方法获取所有构造函数,getConstructors()方法获取所有公有构造函数。

Class<?> clazz = Class.forName("com.***.demo.Person");

//获取所有的构造函数
Constructor<?>[] constructors0 = clazz.getDeclaredConstructors();
for (Constructor<?> constructor : constructors0) {
    System.out.println(constructor);
}
//打印结果
//private com.***.demo.Person(java.lang.String,int)
//protected com.***.demo.Person(java.lang.String)
//public com.***.demo.Person()

Constructor<?>[] constructors1 = clazz.getConstructors();
for (Constructor<?> constructor : constructors1) {
    System.out.println(constructor);
}
//打印结果
//public com.***.demo.Person()

2、getConstructor(Class<?>... parameterTypes)获取公有构造函数,getDeclaredConstructor(Class<?>… parameterTypes)获取其他作用域的构造函数。

Class<?> clazz = Class.forName("com.***.demo.Person");

//公有构造函数的获取
Constructor<?> constructor = clazz.getConstructor();
Object obj = constructor.newInstance();
System.out.println(obj);
//打印结果
//Person{name='null', age=0}
//其他作用域的构造函数的获取
Constructor<?> constructor = clazz.getDeclaredConstructor(String.class);
Object obj = constructor.newInstance("ZhangSan");
 System.out.println(obj);
 //打印结果
 //Person{name='ZhangSan', age=0}
Class<?> clazz = Class.forName("com.huangwei.rpc.demo.Person");

//私有化的构造方法获取
//普通数据类型为对应包装类的TYPE
Constructor<?> constructor = clazz.getDeclaredConstructor(String.class,Integer.TYPE);
constructor.setAccessible(true);//开启暴力反射
Object obj = constructor.newInstance("ZhangSan",18);
System.out.println(obj);
 //打印结果
 //Person{name='ZhangSan', age=18}

三、获取类的属性

1、getDeclaredFields()方法获取所有属性,getFields()获取所有公有属性。

Person person = new Person("ZhangSan");
person.age = 18;
Class<? extends Person> clazz = person.getClass();

//获取类的公有属性
Field[] fields0 = clazz.getDeclaredFields();
for (Field field : fields0) {
    field.setAccessible(true);//开启暴力反射
    System.out.println(field.get(person));
}
 //打印结果
 //ZhangSan
 //18

//获取类的公有属性
Field[] fields1 = clazz.getFields();
for (Field field : fields1) {
    System.out.println(field.get(person));
}
 //打印结果
 //18

2、getField(String name)获取公有属性进行操作,getDeclaredField(String name)获取其他属性进行操作。

Class<?> clazz = Class.forName("com.***.demo.Person");
Object obj = clazz.newInstance();

//通过反射操作public属性
Field field0 = clazz.getField("age");
field0.setInt(obj,28);
System.out.println(field0.get(person));
 //打印结果
 //28

//通过反射操作非公有属性
Field field = clazz.getDeclaredField("name");
field.setAccessible(true);//开启暴力反射
field.set(obj,"LiSi");  //修改私有属性
System.out.println(field.get(obj));  //获取私有属性
 //打印结果
 //LiSi

四、获取类的方法

1、getDeclaredMethods()获取所有非构造方法(包括父类及接口的方法),getMethods()获取所有public非构造方法(包括父类及接口的方法)

Class<?> clazz = Class.forName("com.***.demo.Person");

Method[] methods0 = clazz.getMethods();
for (Method method : methods0) {
    System.out.println(method.getName());
}

Method[] methods1 = clazz.getDeclaredMethods();
for (Method method : methods1) {
    System.out.println(method.getName());
}

2、getDeclaredMethod(String name, Class<?>... parameterTypes)获取本对象的方法,getMethod(String name, Class<?>… parameterTypes)获取公有方法,第一个参数为方法名,第二个参数可变数组是参数类型,按照方法参数顺序进行定义

Class<?> clazz = Class.forName("com.***.demo.Person");
Object obj = clazz.newInstance();

//获取无参数的方法,第二个参数为可变数组,调用方法没有参数时,第二个参数可以省略不写
Method method0 = clazz.getMethod("getName");
method0.invoke(obj);  //获取姓名

//获取基类Object下的方法
Method method1 = clazz.getMethod("equals", Object.class);
method1.invoke(obj, new Person());  //false

//获取私有化的方法
Method method3 = clazz.getDeclaredMethod("setName", String.class);
method3.setAccessible(true);  //开启暴力反射
//调用私有方法
method3.invoke(obj,"ZhangSan");   //姓名写入中...

//多参数的方法,对应参数类型入参
Method method4 = clazz.getDeclaredMethod("init", String.class, int.class);
method4.setAccessible(true);  //开启暴力反射
//调用私有方法
method4.invoke(obj,"ZhangSan",18);  //进行初始化...

// method获取对象的Class(Constructor,Field 都有这个方法)
Class<?> aClass = method.getDeclaringClass();

反射在java.lang.reflect包下,反射影响性能,能直接实现就不用反射。

上一篇:什么是反射?可以解决什么问题?


下一篇:Mybatis整合Spring思路