Java лямбда-метод и новый объект - PullRequest
0 голосов
/ 30 апреля 2018

У меня есть следующий код:

public class RefDemo {

    static class Demo implements Runnable {

        public Demo() {
            System.out.println(this.toString() + "-----");
        }

        @Override
        public void run() {
            System.out.println("run");
        }
    }

    public static void main(String[] args) {
        Runnable runnable = Demo::new; // lambda ref constructor method
        runnable.run(); // does not do anything
        System.out.println(runnable);
        Runnable demo = new Demo(); // using new to create a Demo instance
        demo.run();
        System.out.println(demo);
    }
}

Какие отпечатки:

RefDemo$Demo@7291c18f----- // lambda run constructor method print
RefDemo$$Lambda$1/793589513@34a245ab // main method print
RefDemo$Demo@7cc355be-----
run
RefDemo$Demo@7cc355be

Я не знаю, почему код не печатает run при вызове runnable.run();

Почему это происходит?

Ответы [ 4 ]

0 голосов
/ 30 апреля 2018

Строки:

Runnable runnable = Demo::new;
runnable.run();

эквивалентны:

Runnable runnable = new Runnable() {
    @Override
    public void run() {
        new Demo(); // Creates an instance of the Demo class, and nothing more
    }
};
runnable.run();

В то же время вы намеревались вызвать метод run из класса Demo через ссылку на метод. Поэтому, я полагаю, вы имели в виду следующее:

Runnable runnable = new Demo()::run;
runnable.run();
// But, this is a little bit redundant...

Вышеуказанный код эквивалентен:

Demo demo = new Demo();
Runnable runnable = new Runnable() {
    @Override
    public void run() {
        demo.run();
    }
};
runnable.run();

P.S. Здесь вам не нужна ссылка на метод, поэтому просто напишите:

new Demo().run();

Или:

Runnable demo = new Demo();
demo.run();
0 голосов
/ 30 апреля 2018

Вы просто используете Runnable в слишком многих местах и ​​путаете себя. Следующий код проясняет, что происходит:

public class RefDemo {

    static class Demo {

        public Demo() {
            System.out.println(this.toString() + "-----");
        }

        public void something() {
            System.out.println("something");
        }
    }

    public static void main(String[] args) {
        Runnable runnable = Demo::new; 
        runnable.run();

        System.out.println(runnable);

        Demo demo = new Demo();
        demo.something();

        System.out.println(demo);
    }
}

Runnable runnable = Demo::new; означает, что теперь у вас есть ссылка на конструктор Demo (который все еще работает после удаления соответствия интерфейсу Runnable). И вы сохраняете эту ссылку в переменной типа Runnable, которая работает только потому, что их функциональные интерфейсы совместимы. Вызов run для этой ссылки затем просто вызывает конструктор, не метод run / something Demo.

0 голосов
/ 30 апреля 2018

Этот код

Runnable runnable = Demo::new;

Эквивалентно этому коду

Runnable runnable = new Runnable() {
    @Override 
    public void run() {
        new Demo();
    }
};

То есть вы обращаетесь не к методу run Demo, а к конструктору.

0 голосов
/ 30 апреля 2018

Demo::new является конструктором класса Demo. Поскольку вы присваиваете ссылку на интерфейс Runnable, вызов runnable.run() вызывает конструктор и создает новый экземпляр Demo. Метод run() не выполняется.

Если вы хотите определить Runnable экземпляр, который вызывает Demo 'run() метод, используя ссылку на метод, вы можете написать:

Runnable runnable = new Demo()::run;

Конечно, поскольку Demo уже реализует Runnable, гораздо проще просто написать:

Runnable runnable = new Demo();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...