Jan*_*sen 11 java lambda java-8
在Java中,使用lambda而不是匿名类可以优雅地实现具有单个抽象方法(即SAM类型或功能接口)的接口:
// SAM ActionListener with anonymous implementation
button.addActionListener(
new ActionListener(){
public void actionPerformed(Event e){
System.out.println("button via anon!");
}
}
);
Run Code Online (Sandbox Code Playgroud)
可以替换为:
// SAM ActionListener with lambda implementation
button.addActionListener(
e -> System.out.println("button via lambda!")
);
Run Code Online (Sandbox Code Playgroud)
但对于具有多个抽象方法的接口,无法直接应用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!");
}
}
);
Run Code Online (Sandbox Code Playgroud)
但是有一个更优雅的方式与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!");
}
}
Run Code Online (Sandbox Code Playgroud)
注意:@ maythesource.com提出了一个类似但更广泛的问题:" 如果想要在匿名类中实现多个方法,那么有人会使用MouseListener做什么? "最受欢迎和接受的答案是使用匿名实现.我的问题是关于非SAM类型的优雅lambda解决方案.因此,这个问题是不是重复的的Java 8 Lambda表达式-怎么样在嵌套类中的多个方法.
在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); }
};
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
每个工厂方法都创建一个子类,WindowAdapter它会覆盖相应的方法来调用传入的lambda表达式.不需要额外的适配器或桥接类.
它将使用如下:
window.addWindowListener(WLFactory.windowOpened(we -> System.out.println("opened")));
Run Code Online (Sandbox Code Playgroud)
我发现的最优雅的方法是使用匿名桥:
// SAM bridge with lambda implementation
window.addWindowListener(
WindowBridge.windowOpened(
b -> System.out.println("opening via lambda!")
)
);
Run Code Online (Sandbox Code Playgroud)
与 SAM 类型场景一样,它比匿名适配器更干净:
// non-SAM with adapter implementation with override
window.addWindowListener(
new WindowAdapter() {
@Override
public void windowOpened(Event e){
System.out.println("WindowAdapter opened via override!");
}
}
);
Run Code Online (Sandbox Code Playgroud)
但它确实需要一个带有静态工厂的有点尴尬的桥:
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);
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1712 次 |
| 最近记录: |