Быстро Java Анонимный вопрос о функции / классе - PullRequest
2 голосов
/ 10 июля 2020

Я знаю, как работают анонимные функции в 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 или мне чего-то не хватает?

Надеюсь, что я четко объяснил это, и заранее спасибо!

Ответы [ 2 ]

6 голосов
/ 10 июля 2020

Синтаксис, который предлагает вам IntelliJ, больше не является «наклонным» переводом вашего исходного кода и фактически не отменяет Thread.run, как это делает ваш исходный код.

Исходный код создает анонимный подкласс Thread с переопределением run, тогда как предлагаемый синтаксис IntelliJ вызывает этот конструктор из Thread, который принимает Runnable. Лямбда-выражение представляет Runnable. Если мы «расширим» лямбда-выражение в анонимный класс, мы фактически сделаем это:

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

Итак, мы создаем анонимную реализацию Runnable и вместо этого реализуем Runnable.run.

Он нигде не указывает, что он переопределяет функцию run().

Верно, но run - единственный абстрактный метод в интерфейсе Runnable, поэтому Java может определить, что вы переопределяете этот метод.

3 голосов
/ 10 июля 2020

Функция run() неявно переопределяется, потому что это единственный метод интерфейса Runnable, который делает его функциональным интерфейсом . Функциональный интерфейс имеет ровно один абстрактный метод. Это специальное свойство интерфейса позволяет вам реализовать его неявно с помощью лямбда-выражения. Компилятор знает, что вы предоставляете реализацию метода Runnable.run(), потому что это единственный метод внутри интерфейса.

Если вы посмотрите на интерфейс Runnable, вы Увидим, что он украшен аннотацией @FunctionalInterface. Эта аннотация гарантирует, что в оформленном интерфейсе никогда не может быть более одного абстрактного метода (иначе компилятор выйдет из строя). Обратите внимание, что эта аннотация не требуется для работы неявной лямбда-функции.

...