当前位置: 首页 > 知识库问答 >
问题:

用于具有非SAM接口的lambda的Java习惯用法

斜向文
2023-03-14

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

    // 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有七个方法。但通常一个块代码只对定义这七个方法中的一个感兴趣。

    // non-SAM with adapter implementation with override
    window.addWindowListener(
        new WindowAdapter() {
            @Override
            public void windowOpened(Event e){
                System.out.println("WindowAdapter opened via override!");
            }
        }
    );
@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表达式的重复--嵌套类中的多个方法怎么办。

共有1个答案

魏刚豪
2023-03-14

在Brian Goetz对另一个问题的回答中,他建议使用静态工厂方法。在这种情况下,它有点乏味,因为windowlistener定义了七个处理程序方法,所以需要定义七个静态工厂方法。不过,这并不是那么糟糕,因为已经有一个WindowAdapter类提供了所有方法的空实现。(如果没有,您必须定义自己的等价物。)我会这样做:

class WLFactory {
    public static WindowListener windowOpened(Consumer<WindowEvent> c) {
        return new WindowAdapter() {
            @Override public void windowOpened(WindowEvent e) { c.accept(e); }
        };
    }

    public static WindowListener windowClosing(Consumer<WindowEvent> c) {
        return new WindowAdapter() {
            @Override public void windowClosing(WindowEvent e) { c.accept(e); }
        };
    }

    // ...
}

(其他253例情况类似。)

每个工厂方法都创建windowadapter的子类,该子类重写适当的方法以调用传入的lambda表达式。不需要额外的适配器或桥类。

window.addWindowListener(WLFactory.windowOpened(we -> System.out.println("opened")));
 类似资料:
  • 问题内容: 在Java中,可以使用lambda而不是匿名类优雅地实现具有单个抽象方法的接口(即SAM类型或功能接口): 可以替换为: 但是对于具有多种抽象方法的接口,lambda无法直接应用。例如,有七个方法。但是通常一大段代码只对定义这七个方法之一感兴趣。 要使用匿名类重写来实现该行为,我们可以: 但是lambdas是否有更优雅的方式? 注意 :@ maythesource.com提出了一个类似

  • 问题内容: 随处可见Java 8 lambda。当我向接口添加其他方法时,为什么这会给我一个错误: 在没有第二种方法的情况下可以正常工作:“ public int getID(String name) 问题答案: Java lambda和方法引用只能分配给 功能接口 。从Java SE 8 API中,软件包描述: 每个函数接口都有一个单一的抽象方法,称为该函数接口的函数方法,lambda表达式的参

  • 我已经为使用者接口尝试了类似这样的lambda表达式,它没有问题。其他一些lambda表达式不起作用,因为它们返回一些东西,如。 编译和执行没有问题。 所以我遇到的问题是,我认为像这样的lambda表达式总是等效于,所以我希望编译器会给我一个错误,因为您不能从使用者接口返回(或任何其他类型)。显然,编译器正在将lambda表达式转换为一个方法,如果没有return语句,并且调用方法而不实际返回值。

  • 我有以下静态工厂实现: FirstHandler和SecondHandler都实现以下接口: 请求对象是两个附加类的基类,其中包含请求的附加数据。 在我的主课上,我试着做以下几点: 请求的源由HTTP请求体提供,它可以解析为请求子类中的任何一个。我得到的编译错误是:“必需类型:捕获?扩展请求,提供请求”。 我知道请求对象不会扩展自身,这听起来很奇怪,但有没有办法这样调用handle方法?

  • 如果目标类具有多个接口方法,是否有方法使用lambdas?或者,在这种情况下,您是否只需要使用匿名内部类?

  • 问题内容: 好的,这是我的问题: 我有一个包含interfaces的列表-和扩展该接口的接口的列表:。我要设置。我不希望使用任何东西或会花费更多内存的东西,因为我正在做的事情已经非常耗费成本。我确实需要能够说。我已经尝试过,但是后来我无法将接口添加到列表中,只能将SubInterfaces 添加到列表中。有什么建议? 我希望能够做这样的事情: RecordKeeper类是包含接口列表的类(NOT