Java反射机制
反射机制简介
反射是Java提供的一种在运行时检查、修改程序结构和行为的能力,它允许程序在运行时获取类的信息并操作类的属性和方法。
反射的基本概念
// 获取Class对象的方式
// 1. 通过类名
Class> clazz1 = String.class;
// 2. 通过对象
String str = "Hello";
Class> clazz2 = str.getClass();
// 3. 通过类名字符串
try {
Class> clazz3 = Class.forName("java.lang.String");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
获取类信息
通过反射可以获取类的各种信息,包括类名、包名、父类、接口等。
public class ReflectionDemo {
public static void main(String[] args) {
Class> clazz = String.class;
// 获取类名
System.out.println("类名:" + clazz.getName());
System.out.println("简单类名:" + clazz.getSimpleName());
// 获取包名
Package pkg = clazz.getPackage();
System.out.println("包名:" + pkg.getName());
// 获取父类
Class> superClass = clazz.getSuperclass();
System.out.println("父类:" + superClass.getName());
// 获取实现的接口
Class>[] interfaces = clazz.getInterfaces();
for (Class> iface : interfaces) {
System.out.println("接口:" + iface.getName());
}
}
}
构造方法
通过反射可以获取和调用类的构造方法。
public class ConstructorDemo {
public static void main(String[] args) throws Exception {
Class> clazz = String.class;
// 获取所有公共构造方法
Constructor>[] constructors = clazz.getConstructors();
for (Constructor> constructor : constructors) {
System.out.println("构造方法:" + constructor);
}
// 获取指定参数类型的构造方法
Constructor> constructor = clazz.getConstructor(byte[].class);
// 创建实例
byte[] bytes = "Hello".getBytes();
String str = (String) constructor.newInstance(bytes);
System.out.println("创建的字符串:" + str);
}
}
字段
通过反射可以获取和修改类的字段值。
public class FieldDemo {
public static void main(String[] args) throws Exception {
Class> clazz = Person.class;
// 获取所有公共字段
Field[] fields = clazz.getFields();
for (Field field : fields) {
System.out.println("字段:" + field.getName());
}
// 获取指定名称的字段
Field nameField = clazz.getField("name");
// 创建实例并设置字段值
Person person = new Person();
nameField.set(person, "张三");
System.out.println("姓名:" + nameField.get(person));
// 获取私有字段
Field ageField = clazz.getDeclaredField("age");
ageField.setAccessible(true);
ageField.set(person, 25);
System.out.println("年龄:" + ageField.get(person));
}
}
方法
通过反射可以获取和调用类的方法。
public class MethodDemo {
public static void main(String[] args) throws Exception {
Class> clazz = String.class;
// 获取所有公共方法
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println("方法:" + method.getName());
}
// 获取指定名称和参数类型的方法
Method substring = clazz.getMethod("substring", int.class, int.class);
// 调用方法
String str = "Hello World";
String result = (String) substring.invoke(str, 0, 5);
System.out.println("子字符串:" + result);
// 调用私有方法
Method privateMethod = clazz.getDeclaredMethod("privateMethod");
privateMethod.setAccessible(true);
privateMethod.invoke(str);
}
}
注解
通过反射可以获取和处理类的注解信息。
// 自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
String value() default "";
}
// 使用注解
@MyAnnotation("测试类")
public class AnnotatedClass {
// 类的内容
}
// 获取注解信息
public class AnnotationDemo {
public static void main(String[] args) {
Class> clazz = AnnotatedClass.class;
// 获取类上的注解
MyAnnotation annotation = clazz.getAnnotation(MyAnnotation.class);
if (annotation != null) {
System.out.println("注解值:" + annotation.value());
}
// 获取所有注解
Annotation[] annotations = clazz.getAnnotations();
for (Annotation ann : annotations) {
System.out.println("注解:" + ann.annotationType().getName());
}
}
}
动态代理
Java反射机制支持动态代理,可以在运行时创建代理类。
// 接口
public interface UserService {
void addUser(String name);
void deleteUser(String name);
}
// 实现类
public class UserServiceImpl implements UserService {
@Override
public void addUser(String name) {
System.out.println("添加用户:" + name);
}
@Override
public void deleteUser(String name) {
System.out.println("删除用户:" + name);
}
}
// 代理处理器
public class LoggingHandler implements InvocationHandler {
private Object target;
public LoggingHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("调用方法:" + method.getName());
Object result = method.invoke(target, args);
System.out.println("方法调用完成");
return result;
}
}
// 使用动态代理
public class ProxyDemo {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
UserService proxy = (UserService) Proxy.newProxyInstance(
userService.getClass().getClassLoader(),
userService.getClass().getInterfaces(),
new LoggingHandler(userService)
);
proxy.addUser("张三");
proxy.deleteUser("李四");
}
}
实践练习
练习1:实现一个简单的对象复制器
public class ObjectCopier {
public static T copy(T source) {
// 使用反射实现对象复制
// 复制所有字段的值
}
}