反射
Java的反射(Reflection)是一种允许程序在运行时动态访问、检测和修改自身结构和行为的机制。 通过反射,Java代码可以获取类的信息(如类名、方法、字段、构造器等), 甚至操作类的私有成员、动态创建对象、调用方法等。以下是反射的核心概念和用法:
|
为什么叫“反射”? “反射”这一名称来源于“程序能够像镜子一样观察自身结构”的比喻:
反射(Reflection) 的字面意义是“映射、倒影”。 在编程中,它表示程序在运行时可以“反向映射”自身的结构, 例如类的定义、方法、属性等元数据。 反射机制让程序不再局限于“静态”的代码结构, 而是可以在运行时动态“反映”出类的内部细节,从而实现灵活的编程。
|
核心作用
反射的核心作用:
- 动态获取类的信息:在运行时分析类的结构。
- 动态创建对象:通过类名实例化对象。
- 动态调用方法:根据方法名和参数调用方法。
- 访问私有成员:突破访问权限限制(需主动授权)。
- 通用框架开发:如
Spring
、Hibernate
等框架依赖反射实现依赖注入、动态代理等。
反射的核心类
Class
类:表示一个类或接口,是所有反射操作的入口。
获取类的class对象:
通过类名.class:
Class<User> clazz = User.class;
|
通过对象实例的getClass()方法:
User user = new User(); Class<?> clazz = user.getClass();
|
通过Class.forName(“全限定类名”):
Class<?> clazz = Class.forName("com.example.User");
|
创建对象实例:
User user = clazz.newInstance();
Constructor<?> constructor = clazz.getConstructor(String.class, int.class); User user = (User) constructor.newInstance("Alice", 25);
|
调用方法:
Method method = clazz.getMethod("setName", String.class); method.invoke(user, "Bob");
Method privateMethod = clazz.getDeclaredMethod("privateMethod"); privateMethod.setAccessible(true); privateMethod.invoke(user);
|
访问字段(属性):
Field field = clazz.getDeclaredField("name"); field.setAccessible(true); field.set(user, "Charlie"); String name = (String) field.get(user);
|
Constructor
类:表示类的构造方法,用于创建对象。
和类名一样的函数:
public class MyClass { public MyClass(String name) { System.out.println("公共构造方法调用,name: " + name); } }
Constructor<MyClass> constructor = MyClass.class.getConstructor(String.class); MyClass obj = constructor.newInstance("Alice");
|
常用命令执行类:ProcessBuilder
Class clazz = Class.forName("java.lang.ProcessBuilder"); ((ProcessBuilder) clazz.getConstructor(List.class).newInstance(Arrays.asList("calc.exe"))).star t();
Class clazz = Class.forName("java.lang.ProcessBuilder"); clazz.getMethod("start").invoke(clazz.getConstructor(List.class).newInstance( Arrays.asList("calc.exe")));
|
核心是invoke(调用)
方法
获取 Method
对象:
获取公共方法(包括继承的)。 Class.getMethod(String name, Class<?>... parameterTypes)
Class clazz = Class.forName("java.lang.Runtime"); clazz.getMethod("exec", String.class).invoke(clazz.getMethod("getRuntime").invoke(clazz), "calc.exe");
获取本类中声明的方法(包括私有方法)。 Class.getDeclaredMethod(String name, Class<?>... parameterTypes)
Class clazz = Class.forName("java.lang.Runtime"); Constructor m = clazz.getDeclaredConstructor(); m.setAccessible(true); clazz.getMethod("exec", String.class).invoke(m.newInstance(), "calc.exe");
setAccessible ,这个是必须的。
|
示例:
import java.lang.reflect.Method;
public class Demo { public static void main(String[] args) throws Exception { Method method = String.class.getMethod("toUpperCase"); String str = "hello"; Object result = method.invoke(str); System.out.println(result); } }
|
示例2:带参数
import java.lang.reflect.Method;
public class MathUtils { public static int add(int a, int b) { return a + b; } }
public class Demo { public static void main(String[] args) throws Exception { Method method = MathUtils.class.getMethod("add", int.class, int.class); Object result = method.invoke(null, 3, 5); System.out.println(result); } }
|
Field
类:表示类的字段(成员变量),用于读写字段值。
final Field field = getField(obj.getClass(), fieldName); field.set(obj, value);
|
Modifier
类:解析类、方法或字段的修饰符(如public
、private
)。
恶意类示例
import java.lang.Runtime; import java.lang.Process; public class TouchFile { static { try { Runtime rt = Runtime.getRuntime(); String[] commands = {"touch", "/tmp/success"}; Process pc = rt.exec(commands); pc.waitFor(); } catch (Exception e) { } } }
|