匿名内部类的使用&场景Java的反射机制
·
匿名内部类的使用场景
要求:
使用匿名内部类来封装一个需要计时的任务,在调用任务前后记录时间,从而计算执行耗时。
代码
public class TimeUtil {
// 定义一个任务接口
interface Task {
void execute();
}
// 计时方法,接收一个 Task 实例(可使用匿名内部类传入)
public static double measureSeconds(Task task) {
long start = System.nanoTime();
task.execute();
long end = System.nanoTime();
return (end - start) / 1_000_000_000.0; // 转换为秒
}
public static void main(String[] args) {
// 使用匿名内部类传入需要计时的代码块
double seconds = measureSeconds(new Task() {
@Override
public void execute() {
// 这里放你想测量执行时间的方法
try {
Thread.sleep(500); // 模拟耗时操作,500毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
// 或者调用其他业务方法
// someMethod();
}
});
System.out.printf("方法执行了 %.3f 秒\n", seconds);
}
}
使用匿名内部类优点:
避免为一次性任务单独创建一个类文件,代码更紧凑。
可以直接访问所在方法的局部变量
Java的反射机制
何为反射
反射(Reflection) 是 Java 语言中一种强大的机制,它允许运行中的程序获取自身或任意类的内部信息(如成员变量、方法、构造器),并能动态地创建对象、调用方法、修改属性,甚至打破封装性(访问 private 成员)。简单说:反射让 Java 从“静态语言”在运行时具备了某种“动态语言”的特性。
为什么需要反射
很多框架(Spring、MyBatis、Hibernate)在编译时并不知道你会定义哪些类,但它们需要扫描、实例化、调用你的类 —— 这时就必须依靠反射。
反射的核心类
| 类名 | 作用 |
| Class | 代表一个类或接口,反射的入口 |
| Constructor | 代表构造方法 |
| Method | 代表普通方法 |
| Field | 代表成员变量 |
| Parameter | 代表方法参数(Java 8+) |
| Modifier | 解析访问修饰符(public, private 等) |
获取Class对象的三种方式
// 方式1:通过类的静态属性 .class
Class<User> clazz1 = User.class;
// 方式2:通过对象的 getClass() 方法
User user = new User();
Class<? extends User> clazz2 = user.getClass();
// 方式3:通过 Class.forName() 全限定类名(最常用,动态加载)
Class<?> clazz3 = Class.forName("com.example.User");
常用反射操作
通过反射创建对象
// 1. 调用无参构造
User obj = (User) clazz.getDeclaredConstructor().newInstance();
// 2. 调用有参构造
Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
User obj2 = (User) constructor.newInstance("张三", 25);
获取并调用方法
// 获取 public 方法
Method method = clazz.getMethod("setName", String.class);
method.invoke(obj, "李四");
// 获取 private 方法(需暴力反射)
Method privateMethod = clazz.getDeclaredMethod("secretMethod");
privateMethod.setAccessible(true); // 打破封装
privateMethod.invoke(obj);
获取并修改字段
Field field = clazz.getDeclaredField("age");
field.setAccessible(true);
field.set(obj, 30);
System.out.println(field.get(obj)); // 输出 30
完整示例
public class ReflectDemo {
public static void main(String[] args) throws Exception {
// 1. 获取 Class
Class<?> clazz = Class.forName("com.example.User");
// 2. 创建对象(无参构造)
Object user = clazz.getDeclaredConstructor().newInstance();
// 3. 调用 setName 方法
Method setName = clazz.getMethod("setName", String.class);
setName.invoke(user, "王小明");
// 4. 调用 getName 方法并打印
Method getName = clazz.getMethod("getName");
String name = (String) getName.invoke(user);
System.out.println("用户名:" + name);
// 5. 直接修改私有字段 age
Field ageField = clazz.getDeclaredField("age");
ageField.setAccessible(true);
ageField.set(user, 22);
System.out.println("年龄:" + ageField.get(user));
}
}
反射优缺点
优点
动态性:运行期决定加载哪个类、调用哪个方法,利于实现框架。
通用性:编写不依赖具体类型的代码(如 JSON 解析库、ORM 工具)。
调试/测试工具:可绕过 private 限制进行单元测试或依赖注入。
缺点
性能开销:反射调用比正常调用慢(因为涉及动态解析、安全检查)。JVM 很难优化反射代码。
安全问题:setAccessible(true) 破坏了封装性,可能引发安全风险。
代码可读性下降:反射代码更为晦涩,且 IDE 不提供方法/字段名的自动重构。
更多推荐



所有评论(0)