具有非SAM接口的lambdas的Java习惯用法 [英] Java idiom for lambdas with non-SAM interfaces

查看:128
本文介绍了具有非SAM接口的lambdas的Java习惯用法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Java中,使用lambda而不是匿名类可以优雅地实现具有单个抽象方法的接口(即SAM类型或功能接口):

In Java, interfaces with a single abstract method (i.e., SAM types or functional interfaces) can be elegantly implemented with lambda instead of an anonymous class:

    // SAM ActionListener with anonymous implementation
    button.addActionListener(
        new ActionListener(){
            public void actionPerformed(Event e){
                System.out.println("button via anon!");
            }
        }
    );

可替换为:

    // SAM ActionListener with lambda implementation
    button.addActionListener(
        e -> System.out.println("button via lambda!")
    );

但对于具有多种抽象方法的接口,无法直接应用lambda。例如, java.awt.event.WindowListener 有七种方法。但通常一块代码只对定义这七种方法中的一种感兴趣。

But for interfaces with multiple abstract methods, lambda cannot be directly applied. For example, java.awt.event.WindowListener has seven methods. But often a chunk a code is only interested in defining one of these seven methods.

要实现匿名类覆盖的行为,我们可以:

To implement the behavior with an anonymous class override, we can:

    // non-SAM with adapter implementation with override
    window.addWindowListener(
        new WindowAdapter() {
            @Override
            public void windowOpened(Event e){
                System.out.println("WindowAdapter opened via override!");
            }
        }
    );

但lambda有更优雅的方式吗?

but is there a more elegant way with lambdas?

@FunctionalInterface
public interface ActionListener {
    void actionPerformed(Event e);
}

public interface WindowListener {
    void windowOpened(Event e);

    void windowClosing(Event e);
}

public class WindowAdapter implements WindowListener {

    public void windowOpened(Event e){
        System.out.println("windowOpened in adapter!");
    }

    public void windowClosing(Event e){
        System.out.println("windowClosing in adapter!");
    }
}






注意:@ maythesource.com问了一个类似但更广泛的问题:如果他们想在匿名类中实现多个方法,那么有人会用MouseListener做什么?最受欢迎和接受的答案是使用匿名实现。我的问题是关于非SAM类型的优雅lambda解决方案。因此, Java 8 Lambda表达式这个问题并不重复 - 嵌套类中的多个方法怎么样


Note: @maythesource.com asked a similar, but broader question: "What would someone do with a MouseListener if they wanted to implement multiple methods within the anonymous class?" The most upvoted and accepted answer is to use an anonymous implementation. My question is about an elegant lambda solution for non-SAM types. Therefore, this question is not a duplicate of Java 8 Lambda Expressions - what about multiple methods in nested class.

推荐答案

我找到的最优雅的方法是使用匿名桥:

The most elegant way I have found is to use an anonymous bridge:

    // SAM bridge with lambda implementation
    window.addWindowListener(
        WindowBridge.windowOpened(
            b -> System.out.println("opening via lambda!")
        )
    );

与SAM类型的情况一样,它比匿名适配器更干净:

which, like the SAM type scenario, is cleaner than the anonymous adapter:

    // non-SAM with adapter implementation with override
    window.addWindowListener(
        new WindowAdapter() {
            @Override
            public void windowOpened(Event e){
                System.out.println("WindowAdapter opened via override!");
            }
        }
    );

但它确实需要一个带有静态工厂的稍微笨拙的桥:

but it does require a slightly awkward bridge with a static factory:

import java.util.function.Consumer;

public interface WindowBridge {

    // SAM for this method
    public abstract class WindowOpened extends WindowAdapter {
        public abstract void windowOpened(Event e);
    }

    // factory bridge
    public static WindowOpened windowOpened(Consumer<Event> c) {
        return new WindowOpened() {
            public void windowOpened(Event e){
                c.accept(e);
            }
        };
    }

    // SAM for this method
    public abstract class WindowClosing extends WindowAdapter {
        public abstract void windowClosing(Event e);
    }

    // factory bridge
    public static WindowClosing windowClosing(Consumer<Event> c) {
        return new WindowClosing() {
            public void windowClosing(Event e){
                c.accept(e);
            }
        };
    }
}

这篇关于具有非SAM接口的lambdas的Java习惯用法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆