Java 8 Lambdaexpression式 – 嵌套类中的多个方法
我正在阅读有关新function: http : //www.javaworld.com/article/2078836/java-se/love-and-hate-for-java-8.html
我看到下面的例子:
使用匿名类:
button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { System.out.println("Action Detected"); } });
随着Lambda:
button.addActionListener(e -> { System.out.println("Action Detected"); });
如果他们想要在匿名类中实现多个方法,有人会用MouseListener
做什么,例如:
public void mousePressed(MouseEvent e) { saySomething("Mouse pressed; # of clicks: " + e.getClickCount(), e); } public void mouseReleased(MouseEvent e) { saySomething("Mouse released; # of clicks: " + e.getClickCount(), e); }
… 等等?
来自JLS 9.8
function接口是一个只有一个抽象方法的接口,因此代表一个单一的function合同。
Lambda需要这些function接口,因此仅限于单一方法。 匿名接口仍然需要用于实现多方法接口。
addMouseListener(new MouseAdapter() { @Override public void mouseReleased(MouseEvent e) { ... } @Override public void mousePressed(MouseEvent e) { ... } });
您可以使用帮助程序接口与lambdaexpression式一起使用多方法接口。 这适用于这样的监听器接口,其中不需要的方法的实现是微不足道的(即我们可以做什么MouseAdapter
提供):
// note the absence of mouseClicked… interface ClickedListener extends MouseListener { @Override public default void mouseEntered(MouseEvent e) {} @Override public default void mouseExited(MouseEvent e) {} @Override public default void mousePressed(MouseEvent e) {} @Override public default void mouseReleased(MouseEvent e) {} }
你只需要定义一个这样的辅助接口一次。
现在,您可以为Component
c
添加一个监听器,如下所示:
c.addMouseListener((ClickedListener)(e)->System.out.println("Clicked !"));
Lambda EG确实考虑过这个问题。 许多库使用function接口,即使它们是在function接口成为事物之前几年devise的。 但是有时确实有一个类有多个抽象方法,你只想用lambda来定位其中的一个。
这里正式推荐的模式是定义工厂方法:
static MouseListener clickHandler(Consumer<MouseEvent> c) { return ... }
这些可以由API本身直接完成(这些可以是MouseListener
静态方法),也可以是其他库中的外部辅助方法,如果维护者select不提供这种便利。 由于需要的情况很less,解决方法如此简单,因此似乎没有必要进一步扩展语言来解决这个问题。
ThreadLocal
采用了类似的技巧; 请参阅withInitial(Supplier<S>)
的新静态工厂方法。
(顺便说一下,当这个问题出现时,这个例子几乎总是MouseListener
,这是令人鼓舞的,因为它暗示了一组希望是lambda友好的类,但是不是,实际上非常小。
Java ActionListener
必须只实现一个方法( actionPerformed(ActionEvent e)
)。 这很适合Java 8的function,所以Java 8提供了一个简单的lambda来实现一个ActionListener
。
MouseAdapter
至less需要两个方法,因此不适合作为function
。
Lambdaexpression式适合于函数接口必须包含一个抽象方法声明
缺省方法不能从lambdaexpression式中访问。 下面的代码不能编译:
interface Formula { double calculate(int a); default double sqrt(int a) { return Math.sqrt(a); } } Formula formula = (a) -> sqrt( a * 100);
只能使用function接口(仅限单一抽象方法+任意数量的默认方法),所以lambdaexpression式只能用抽象方法工作