Можем ли мы использовать лямбда-выражение для WindowListener? если да то как? если нет то почему? Могу ли я установить лямбда-выражение для приведенного ниже фрагмента кода?

this.addWindowListener(new WindowAdaptor(){
public void windowClosing(WindowEvent we)
{
    System.exit(0);//to close the window
}
});

Это моя просьба, пожалуйста, сделайте код, используя лямбда-выражение.


person Manohar    schedule 15.05.2015    source источник
comment
Аналогичная проблема: stackoverflow.com/a/26875548/1393766   -  person Pshemo    schedule 15.05.2015


Ответы (2)


Лямбда-выражение может заменить функциональный интерфейс (т. е. интерфейс с одним методом, отличным от метода по умолчанию). Поэтому WindowAdapter, который имеет несколько методов (windowActivated(WindowEvent e), windowClosed(WindowEvent e), windowClosing(WindowEvent e),...), не может быть заменен лямбда-выражением.

person Eran    schedule 15.05.2015
comment
Краткий справочник по лямбда-выражениям и функциональным интерфейсам: docs.oracle.com/ javase/учебник/java/javaOO/ - person Pshemo; 15.05.2015

Напрямую вы не можете использовать лямбда-выражения здесь, но если у вас довольно много кода пользовательского интерфейса, где у вас много слушателей, вы можете создать такой конструктор:

import java.awt.Window;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.function.Consumer;

public class ListenerBuilder {
    static final Consumer<WindowEvent> nullConsumer = e -> {}; 

    private Consumer<WindowEvent> opened = nullConsumer;
    private Consumer<WindowEvent> closing = nullConsumer;
    private Consumer<WindowEvent> closed = nullConsumer;
    private Consumer<WindowEvent> iconified = nullConsumer;
    private Consumer<WindowEvent> deiconified = nullConsumer;
    private Consumer<WindowEvent> activated = nullConsumer;
    private Consumer<WindowEvent> deactivated = nullConsumer;

    public ListenerBuilder opened(Consumer<WindowEvent> opened) 
    { this.opened = opened; return this; }

    public ListenerBuilder сlosing(Consumer<WindowEvent> closing) 
    { this.closing = closing; return this; }

    public ListenerBuilder closed(Consumer<WindowEvent> closed) 
    { this.closed = closed; return this; }

    public ListenerBuilder iconified(Consumer<WindowEvent> iconified) 
    { this.iconified = iconified; return this; }

    public ListenerBuilder deiconified(Consumer<WindowEvent> deiconified) 
    { this.deiconified = deiconified; return this; }

    public ListenerBuilder activated(Consumer<WindowEvent> activated) 
    { this.activated = activated; return this; }

    public ListenerBuilder deactivated(Consumer<WindowEvent> deactivated) 
    { this.deactivated = deactivated; return this; }

    public WindowListener build() {
        return new WindowListener() {
            public void windowOpened(WindowEvent e) {
                opened.accept(e);
            }
            public void windowIconified(WindowEvent e) {
                iconified.accept(e);
            }
            public void windowDeiconified(WindowEvent e) {
                deiconified.accept(e);
            }
            public void windowDeactivated(WindowEvent e) {
                deactivated.accept(e);
            }
            public void windowClosing(WindowEvent e) {
                closing.accept(e);
            }
            public void windowClosed(WindowEvent e) {
                closed.accept(e);
            }
            public void windowActivated(WindowEvent e) {
                activated.accept(e);
            }
        };
    }

    public void attachTo(Window w) {
        w.addWindowListener(build());
    }
}

После этого его можно использовать следующим образом:

this.addWindowListener(new ListenerBuilder()
    .opened(e -> log.info("Window is opened!"))
    .closed(e -> System.exit(0)).build());

Или вот так:

new ListenerBuilder()
    .opened(e -> log.info("Window is opened!"))
    .closed(e -> System.exit(0)).attachTo(this);
person Tagir Valeev    schedule 15.05.2015
comment
Недостаток этого дизайна заключается в том, что он автоматически перезаписывает обработчик, если метод вызывается более одного раза. Кроме того, сгенерированный слушатель ссылается на обработчики через экземпляр построителя, что делает его изменяемым, а все использование шаблона построителя бессмысленным. - person Holger; 18.05.2015
comment
Несмотря на простую реализацию примера, идея использовать конструктор здесь великолепна. Ломбок может сгенерировать для вас строителя. Автоматически сгенерированный билдер исправляет все упомянутые недостатки. - person Socowi; 16.10.2020