一、什么是反射
反射是可以在运行是获取目标类的所有信息,包括:构造函数、方法、成员变量、包括其中的返回类型、访问修饰符等等...
二、怎么使用反射
1、获取反射对象
package org.reflect;
/**
* @description: 反射
*/
public class TestCar {
//1、获取class对象的方式
@Test
public void getClassObject(){
//创建实例对象
Car car = new Car();
// ① 实例对象.getClass()
Class<? extends Car> aClass1 = car.getClass();
// ② Class.format("类全路径")
try {
Class<?> aClass2 = Class.forName("org.reflect.Car");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
//③ 类名.Class
Class<Car> carClass = Car.class;
}
}
2、获取构造方法
package org.reflect;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Constructor;
/**
* @description: 反射
*/
public class TestCar {
//2、获取构造方法
@Test
public void getConstructorObject(){
// ② Class.format("类全路径")
try {
Class<?> aClass2 = Class.forName("org.reflect.Car");
//获取对应的 public 的构造器
Constructor<?> car1 = aClass2.getConstructor();
Constructor<?> car2 = aClass2.getConstructor(String.class, int.class, String.class);
//private 和 public 都可以获取
Constructor<?> car3 = aClass2.getDeclaredConstructor(String.class);
//创建实例
Car car = (Car) car1.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
3、获取方法
package org.reflect;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* @description: 反射
*/
public class TestCar {
//3、获取方法
@Test
public void getMeObject(){
// ② Class.format("类全路径")
try {
Class<?> aClass2 = Class.forName("org.reflect.Car");
//① 创建实例
Object o = aClass2.newInstance();
//② 获取方法
//②-1获取单个方法 public 类型
Method run = aClass2.getMethod("runPublic");
//②-2获取所有 public 类型的方法
Method[] methods = aClass2.getMethods();
System.out.print("所有public方法:");
for (Method method:methods){
System.out.print(method.getName()+",");
}
System.out.println("");
//运行方法
run.invoke(o);
//②-3获取单个方法,支持 private 和 public
Method runPrivate = aClass2.getDeclaredMethod("runPrivate");
//操作private方法
runPrivate.setAccessible(true);
runPrivate.invoke(o);
//②-4获取所有方法,支持获取 private 和 public
Method[] declaredMethods = aClass2.getDeclaredMethods();
System.out.print("所有方法:");
for (Method method:declaredMethods){
System.out.print(method.getName()+",");
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
4、获取属性
package org.reflect;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* @description: 反射
*/
public class TestCar {
//4、获取属性
@Test
public void getAttr(){
try {
//获取反射对象
Class<?> aClass2 = Class.forName("org.reflect.Car");
//获取 public 有参构造器
Constructor<?> constructor = aClass2.getConstructor( String.class);
Car o = (Car)constructor.newInstance( "黑色");
//获取单个 public 属性
Field price = aClass2.getField("price");
price.set(o,"10.00");
System.out.println("修改后的price:"+o.price);
//获取所有 public 属性
Field[] fields = aClass2.getFields();
System.out.print("------所有public属性名称:");
for (Field f:fields) {
System.out.print(f.getName()+",");
}
System.out.println();
//获取所有属性 包括private
Field[] fields1 = aClass2.getDeclaredFields();
//获取任意单个属性,可private、public...
// Field name = aClass2.getDeclaredField("name");
System.out.print("-----所有属性名称:");
for (Field f:fields1) {
System.out.print(f.getName()+",");
if("price".equals(f.getName())){
f.set(o,"12.44");
}
if("name".equals(f.getName())){
//设置允许设置私有属性
f.setAccessible(true);
f.set(o,"测试私有属性设置");
}
}
System.out.println("修改后的颜色:"+o.price+",名称:"+ o.getName());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
测试类
package org.reflect;
/**
* @description: 反射测试类
*/
public class Car {
//属性
private String name;
private int age;
private String color;
public String price;
//无参构造
public Car() {
System.out.println("无参构造......");
}
private Car(int age) {
System.out.println("private构造......");
}
public Car(String color) {
System.out.println("color构造......"+color);
}
//有参构造
public Car(String name, int age) {
this.name = name;
this.age = age;
System.out.println("有参构造......");
}
//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;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public void runPublic(){
System.out.println("public方法Run......" +
"");
}
private void runPrivate(){
System.out.println("private方法Run......");
}
}
三、反射应用场景
- 框架设计
- 动态代理
- 配置与注解处理
- 单元测试
- 配置与注解处理
四、反射优缺点
优点:
- 灵活性和可扩展性
- 框架和库的支持
缺缺:
- 性能问题
- 安全风险
参考文章