在日常开发中,我们经常需要统计某个方法的执行耗时,来分析性能瓶颈。很多同学会直接在方法前后写 System.currentTimeMillis(),但这样会导致代码冗余、可读性差,也不利于复用。 今天我们就用 Java 匿名内部类 来优雅地解决这个问题,顺便搞懂匿名内部类的核心用法。

一、需求场景 我们需要一个通用工具,能统计任意方法的执行时间,而不用每个方法都写一遍计时逻辑。

应用场景:计算一个方法执行了多少秒!

(homework1) 核心技术:匿名内部类

二、核心思路 定义一个接口,里面只有一个待执行的方法(比如 execute())。

写一个工具方法,接收这个接口的实现,在工具方法里完成 “计时 + 执行逻辑” 的流程。 调用工具方法时,用匿名内部类传入要执行的具体逻辑,实现解耦。

三、完整代码实现

1. 定义执行任务接口

// 定义一个任务接口,代表一个需要被执行的逻辑
public interface Task {
    // 待执行的业务逻辑
    void execute();
}

2. 编写计时工具类

public class TimeUtils {

    /**
     * 统计任务执行时间
     * @param task 要执行的任务,通过匿名内部类传入
     * @return 执行耗时(秒)
     */
    public static double calculateTime(Task task) {
        // 1. 记录开始时间
        long start = System.currentTimeMillis();
        
        // 2. 执行传入的任务逻辑
        task.execute();
        
        // 3. 记录结束时间,计算耗时
        long end = System.currentTimeMillis();
        long costMillis = end - start;
        double costSeconds = costMillis / 1000.0;
        
        System.out.println("方法执行耗时:" + costSeconds + " 秒");
        return costSeconds;
    }
}

3. 使用匿名内部类调用工具

public class Test {
    public static void main(String[] args) {
        
        // 场景1:统计一个循环任务的执行时间
        TimeUtils.calculateTime(new Task() {
            @Override
            public void execute() {
                int sum = 0;
                for (int i = 0; i < 1000000; i++) {
                    sum += i;
                }
                System.out.println("循环执行完毕,sum = " + sum);
            }
        });

        System.out.println("---------------------------");

        // 场景2:统计线程休眠的执行时间
        TimeUtils.calculateTime(new Task() {
            @Override
            public void execute() {
                try {
                    Thread.sleep(1500); // 模拟耗时操作
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("休眠任务执行完毕");
            }
        });
    }
}

四、匿名内部类的核心知识点

1. 什么是匿名内部类?

匿名内部类就是没有名字的内部类,它的本质是: 继承一个类 或 实现一个接口 同时创建这个类的对象 只能使用一次,用完即弃

2. 匿名内部类的语法格式

new 父类/接口() {
    // 重写/实现方法
};

3.在我们的例子里,就是 new Task() { ... },表示创建了一个实现 Task 接口的匿名类对象,重写了 execute() 方法。

. 为什么这里要用匿名内部类?
代码复用:计时逻辑只写一次,所有方法都能复用
解耦清晰:业务逻辑和计时逻辑完全分离
写法简洁:不用为了一个临时任务单独创建一个类
Java 8 兼容:如果用 Lambda 表达式,代码会更简洁(本质也是匿名内部类的语法糖)
4. 扩展:用 Lambda 简化代码(Java 8+)
因为 Task 是一个函数式接口(只有一个抽象方法),可以直接用 Lambda 表达式简化:

public class TestLambda {
    public static void main(String[] args) {
        // Lambda 写法,省略了匿名内部类的模板代码
        TimeUtils.calculateTime(() -> {
            int sum = 0;
            for (int i = 0; i < 1000000; i++) {
                sum += i;
            }
            System.out.println("循环执行完毕,sum = " + sum);
        });
    }
}

五、匿名内部类的常见使用场景 除了计时工具,匿名内部类在开发中还有这些高频场景:

事件监听器:Swing/Android 中给按钮加点击事件 线程任务:创建一次性的 Runnable 任务 Comparator 比较器:给集合排序时临时定义比较规则 临时回调:处理异步操作的回调逻辑

六、总结 匿名内部类的核心价值:为接口 / 抽象类提供一次性的实现,避免创建冗余的类文件。 本次的计时工具案例,完美体现了匿名内部类的优势:代码复用、解耦清晰、写法简洁。 理解了匿名内部类,再看 Lambda 表达式就会非常轻松,它们本质上是同一个东西的不同写法。

更多推荐