Java 8 Lambda表达式 - 嵌套类中的多个方法怎么样

Men*_*los 79 java lambda anonymous-class java-8

我正在阅读以下新功能: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");
    }
});
Run Code Online (Sandbox Code Playgroud)

使用Lambda:

button.addActionListener(e -> {
    System.out.println("Action Detected");
});
Run Code Online (Sandbox Code Playgroud)

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);
}
Run Code Online (Sandbox Code Playgroud)

... 等等?

Rei*_*eus 87

来自JLS 9.8

功能接口是只有一个抽象方法的接口,因此代表单个函数契约.

Lambdas需要这些功能接口,因此仅限于其单一方法.匿名接口仍然需要用于实现多方法接口.

addMouseListener(new MouseAdapter() {

    @Override
    public void mouseReleased(MouseEvent e) {
       ...
    }

    @Override
    public void mousePressed(MouseEvent e) {
      ...
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 来自OP的问题是"**如果有人想在匿名类中实现多个方法,那么有人会用MouseListener做什么,例如:"(强调我的).你给出的答案是好的,但只是说你不能使用包含多个方法的接口来进行lambda描述.[Holger的回答](http://stackoverflow.com/a/21851111/4229245)解释了解决方法.您可以扩展到自己的界面,并为您不需要的方法提供默认值.这留下了一个用于你的lambda.**这不是人们在Java 8代码中看到的第一个令人畏缩的事情.** (13认同)

Hol*_*ger 76

您可以使用辅助接口将多方法接口与lambdas一起使用.这适用于这样的监听器接口,其中不需要的方法的实现是微不足道的(即我们也可以做什么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) {}
}
Run Code Online (Sandbox Code Playgroud)

您只需要定义一次这样的辅助接口.

现在,你可以为这样的点击事件添加一个监听器Component c:

c.addMouseListener((ClickedListener)(e)->System.out.println("Clicked !"));
Run Code Online (Sandbox Code Playgroud)

  • 我相信这个"​​kludge"应该是公认的答案.来自OP的问题显然是"**如果有人想在匿名类中实现多个方法,那么有人会用MouseListener做什么,例如:"(强调我的).当你有一个包含多个方法的接口时,他正在问如何使用lamdas.@Holger完美地回答了这个问题.OP显然*已经*知道如何以非功能方式使用匿名类. (10认同)
  • 对我来说,这似乎是针对MouseListeners这个问题的rococco解决方案.我认为附加一个匿名对象[旧方式]效果更好.在我看来,它是一个kludge. (6认同)
  • @ncmathsadist:如果您愿意,可以随意使用匿名内部类方法。这只是一种选择。你也可以考虑[这个答案](http://stackoverflow.com/a/23373921/2711488)。还有 [其他动态侦听器生成器](http://docs.oracle.com/javase/7/docs/api/java/beans/EventHandler.html#create(java.lang.Class,%20java.lang.Object ,%20java.lang.String,%20java.lang.String,%20java.lang.String))... (2认同)

Bri*_*etz 31

Lambda EG确实考虑过这个问题.许多库使用功能接口,即使它们是在功能接口成为事物之前的几年设计的.但有时会发生一个类有多个抽象方法,而你只想用lambda来定位其中一个.

这里官方推荐的模式是定义工厂方法:

static MouseListener clickHandler(Consumer<MouseEvent> c) { return ... }
Run Code Online (Sandbox Code Playgroud)

这些可以直接由API本身完成(这些可以是其中的静态方法MouseListener),或者如果维护者选择不提供这种便利,则可以是其他库中的外部辅助方法.因为需要这种情况的情况很少,并且解决方法非常简单,所以扩展语言以挽救这个角落的情况似乎并不引人注目.

采用了类似的技巧ThreadLocal; 看到新的静态工厂方法withInitial(Supplier<S>).

(顺便说一下,当这个问题出现时,这个例子几乎总是如此MouseListener,这是令人鼓舞的,因为它表明那些希望对lambda友好的类,但实际上并不是很小.)

  • 另请参阅[此问题](http://stackoverflow.com/q/25299653/1441122).还有一些其他多方法接口,例如`WindowListener`,但它们相对较少. (2认同)