Java的反射机制
是指在运行时检查和操作类、方法、字段等程序组件的能力。通过反射,可以动态地获取类的信息、调用方法、访问字段,而无需在编译时知道这些信息。Java的反射机制提供了一种灵活的方式来操作类和对象,使得程序能够在运行时进行动态的操作和处理。
Java的反射机制主要基于java.lang.reflect包中的类和接口。一些常用的反射类包括:
- Class类:代表一个类或接口,在运行时可以用来获取类的信息,如类名、父类、实现的接口、字段、方法等。
- Method类:代表类的方法,可以通过Method对象调用类的方法。
- Field类:代表类的字段,可以通过Field对象访问和修改类的字段。
- Constructor类:代表类的构造函数,可以通过Constructor对象实例化类的对象。
通过这些反射类,可以实现以下功能:
- 动态加载类:在运行时根据类名动态加载类,创建类的实例。
- 调用方法:通过Method对象调用类的方法,包括公有方法、私有方法、静态方法等。
- 访问字段:通过Field对象访问和修改类的字段,包括公有字段、私有字段等。
- 处理注解:通过反射可以获取类、方法、字段上的注解信息,实现基于注解的编程。
三种获取Class对象的方式
// 第一种, 使用ClassLoader装在类,并对类进行初始化
Class c1= Class.forName("Test");
Object t1 = c1.newInstance();
System.out.println(((Test)t1).getString());
// 第二种,返回类对象运行时真正所指的对象、所属类型的Class对象
Class c2 = new Test().getClass();
Object t2 = c2.newInstance();
System.out.println(((Test)t2).getString());
// 第三种,ClassLoader装入内存,不对类进行类的初始化
Class c3 = Test.class;
Object t3 = c3.newInstance();
System.out.println(((Test)t3).getString());
// 有参数的构造
Constructor<?> csr = c1.getDeclaredConstructor(String.class, int.class);
Object o1 = csr.newInstance("lpf",18);
// 反射类中的属性
// getField : 只能获取public的,包括从父类继承来的字段
// getDeclaredField: 可以获取本类所有的字段,包括private以及继承来的字段
Field field = c1.getDeclaredField("name");
// 使用setAccessible取消Java的权限控制检查,特别是可以取消私有字段访问限制
// public 和 private修饰的属性,默认accessible属性都为false
field.setAccessible(true);
field.set(t1, "lpf");
System.out.println(((Test) t1).getName());
// 修改属性中的修饰符
Field field2 = c1.getDeclaredField("name");
String priv = Modifier.toString(field2.getModifiers());
System.out.println("打印属性修饰符" + priv);
// 反射类中的方法
Method m = c1.getDeclaredMethod("setName",String.class);
m.invoke(o1, "new invoke name");
System.out.println("打印setName后的结果"+((Test)o1).getName());
// 反射静态方法
Class clz = Class.forName("Test");
Method m2 = clz.getDeclaredMethod("getStaticMethod");
m2.invoke(null);
// 反射泛型参数方法
Class clzT = TestT.class;
// 方法中有泛型参数时,编译器会自动类型向上转型,T 向上转型是Object
Method m3 = clzT.getDeclaredMethod("test", Object.class);
m3.setAccessible(true);
m3.invoke(new TestT<Integer>(),1);
动态代理的作用?
在不改变代码的情况下,增加一些方法,在方法执行前后做一些事情
// 定义接口
public interface Subject {
void doSomething();
}
// 具体实现类
public class RealSubject implements Subject{
@Override
public void doSomething() {
System.out.println("Real Subject do something");
}
}
// 代理类
public class ProxyHandler implements InvocationHandler {
private Object realSubject;
public ProxyHandler(Object realSubject) {
this.realSubject = realSubject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 在调用具体目标对象前,可以执行一些具体处理
System.out.println("执行具体对象前...");
Object result = method.invoke(realSubject, args);
System.out.println("执行具体对象后...");
return result;
}
}
// 执行
public static void main(String[] args) {
RealSubject real = new RealSubject();
Subject proxySubject = (Subject) Proxy.newProxyInstance(
Subject.class.getClassLoader(),
new Class[]{Subject.class},
new ProxyHandler(real));
proxySubject.doSomething();
}