【问题标题】:Quick Java Anonymous function/class question快速 Java 匿名函数/类问题
【发布时间】:2020-07-10 02:47:56
【问题描述】:

我知道匿名函数在 JS 中是如何工作的,但我对 Java 中的部分匿名函数有点困惑。

所以下面我有一个匿名类(我只是使用 Thread 类作为我所看到的示例),我在其中重写 run() 函数,然后调用 .start() 在那个类上。

new Thread() {
    @Override
    public void run() {
        System.out.println("Hello from the anonymous class thread");
    }
}.start();

所以这行得通,但 IntelliJ 想让我把它改写成这样:

new Thread(() -> System.out.println("Hello from the anonymous class thread")).start();

我了解了大部分这种语法,但对于如何覆盖 run() 函数有点困惑。据我了解,没有参数被传递给 Thread 类(所以我假设没有任何参数传递给构造函数)。现在我感到困惑的地方就在这里。它没有在任何地方声明它覆盖 run() 函数。这是 Thread 类的特例还是我遗漏了什么?

希望我解释清楚并提前感谢!

【问题讨论】:

    标签: java multithreading lambda java-8 anonymous-class


    【解决方案1】:

    IntelliJ 向您建议的语法并不是您原始代码的“倾斜”翻译,实际上并没有像您的原始代码那样覆盖 Thread.run

    您的原始代码创建了 Thread 的匿名子类,并覆盖了 run,而 IntelliJ 建议的语法调用 Thread 中的 this constructor,接受 Runnable。 lambda 表达式代表Runnable。如果我们将 lambda 表达式“扩展”为匿名类,我们实际上会这样做:

    new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("Hello from the anonymous class thread");
        }
    }).start();
    

    所以我们正在创建Runnable 的匿名实现,并改为实现Runnable.run

    它没有在任何地方声明它覆盖了run() 函数。

    没错,但runRunnable 接口中唯一的抽象方法,因此Java 能够确定您正在覆盖该方法。

    【讨论】:

    • 谢谢!这是一个很好的解释。像以前一样实际覆盖 run() 函数与拥有 new Runnable() 实例然后覆盖 run()有区别吗> 功能?
    • @thatdevopNB 线程应该做同样的事情。但是传入Runnable 对我来说更有意义。见this answer
    【解决方案2】:

    run() 函数被隐式覆盖,因为它是Runnable 接口的唯一方法,这使它成为函数式接口。一个函数式接口只有一个抽象方法。接口的这一特殊属性允许您使用 lambda 表达式隐式实现它。编译器知道您正在提供Runnable.run() 方法的实现,因为它是接口内的唯一方法。

    如果你看一下Runnable 接口,你会发现它被@FunctionalInterface 注释修饰。这个注解确保被修饰的接口永远不能有多个抽象方法(否则编译器会失败)。请注意,为了使隐式 lambda 功能起作用,不需要此注释。

    【讨论】:

      猜你喜欢
      • 2014-03-06
      • 1970-01-01
      • 1970-01-01
      • 2011-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多