什么是反射
简单来说:
反射是可以帮助程序员去获取类的详细信息的一种机制。
Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。
反射应用场景
- 在编译时根本无法知道该对象或类可能属于哪些类,程序只依靠运行时信息来发现该对象和类的真实信息
- 比如:像 Spring/Spring Boot、MyBatis 等等框架中都大量使用了反射机制。
具体详细例子,JDK动态代理,利用反射获取方法的名字
public class DebugInvocationHandler implements InvocationHandler {
/**
* 代理类中的真实对象
*/
private final Object target;
public DebugInvocationHandler(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
System.out.println("before method " + method.getName());
Object result = method.invoke(target, args);
System.out.println("after method " + method.getName());
return result;
}
}
优缺点
1、优点:
使代码更加灵活
2、缺点:
反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。
四种获取类信息的方式
public class TestClass2 {
public static void main(String[] args) throws Exception {
//1.获取一个类的结构信息(类对象 Class对象)
// 1.1Class.forName(类的完整路径字符串);
Class clazz = Class.forName("java.lang.String");
//1.2 类名.class
Class clazz = String.class;
//1.3 对象名.getClass()
String str = "bjsxt";
Class clazz = str.getClass();
//Integer in = new Integer(20);
//1.4 通过类加载器xxxClassLoader.loadClass()传入类路径获取:
ClassLoader.getSystemClassLoader().loadClass("类的完整路径");
//2.从类对象中获取类的各种结构信息
System.out.println(clazz.getName());
System.out.println(clazz.getSimpleName());
System.out.println(clazz.getSuperclass());
System.out.println(Arrays.toString(clazz.getInterfaces()));
}
}
代码示例
public class TestField {
public static void main(String[] args) throws Exception{
//不使用反射操作属
// Dog dog = new Dog();
// dog.nickName = "旺财";
// dog.age ="黑色";
// System.out.println(dog.nickName);
// System.out.println(dog.color);
//使用反射操作属性 实际操作中使用反射直接操作属性也不多
//1.获取类的完整路径字符串
String className = "com.bjsxt.seq.Dog";
//2.得到类对象
Class clazz = Class.forName(className);
//3.使用反射创建对象
//Object dog = clazz.newInstance();
Object dog = clazz.getConstructor().newInstance();
//4.获取属性
Field f1 = clazz.getField("color");
//Field f2 = clazz.getField("age");
Field f2 = clazz.getDeclaredField("age");
//5.给属性赋值
f1.set(dog,"黑色1"); // dog.color ="黑色";
f2.setAccessible(true);//突破权限的控制
f2.set(dog,10);
//6.输出给属性
System.out.println(f1.get(dog)); //dog.color
System.out.println(f2.get(dog)); //dog.age
System.out.println(dog);
}
}
使