带有非 SAM 接口的 lambda 表达式的 Java 习惯用法 [英] Java idiom for lambdas with non-SAM interfaces

查看:22
本文介绍了带有非 SAM 接口的 lambda 表达式的 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 接口的 lambda 表达式的 Java 习惯用法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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