22

我试图区分侦听器和适配器。

它们是否几乎相同,但在侦听器中您必须实现接口中的所有方法,但使用适配器您可以选择只实现您需要的方法,以便代码更简洁且更易于阅读?

我还被告知适配器仅通过一种实现启用实例化,而您不能实例化侦听器,我不完全理解这一点。

有人可以解释一下哪个更好用,以及你可以用一个做的事情,但你不能用另一个做吗?

4

5 回答 5

32

WindowListenerinterface强制你使用override所有方法,而WindowAdapter是实现,WindowListener你只需要override你感兴趣的方法来处理。

WindowListener是接口,这意味着您不能实例化WindowListener,而WindowAdapter是可以使用new运算符进行实例化的具体类。

当你使用WindowAdapter时,代码更干净,你的类只覆盖你想要的方法。例如:

窗口监听器

public class CloseListener implements WindowListener {
    // im not interest  on this event, but still need to override it
    @Override
    public void windowOpened(WindowEvent e) {

    }
    // im not interest  on this event, but still need to override it    
    @Override
    public void windowClosing(WindowEvent e) {

    }

    @Override
    public void windowClosed(WindowEvent e) {
        System.exit(0);

    }
    // im not interest  on this event, but still need to override it    
    @Override
    public void windowIconified(WindowEvent e) {

    }
    // im not interest  on this event, but still need to override it
    @Override
    public void windowDeiconified(WindowEvent e) {

    }

}

窗口适配器

使用适配器时,代码更干净:

// at JFrame class
addWindowListener(new CloseListener());

// reusable Close Listener
public class CloseListener extends WindowAdapter {
    @Override
    public void windowClosed(WindowEvent e) {
        System.exit(0);
    }
}

或者

addWindowListener(new WindowAdapter() {
    @Override
    public void windowClosed(WindowEvent e) {
         System.exit(0);
     }
});

所以我会推荐使用WindowAdapter,但不是必须遵循。但是,两个 API 大致相同,只是为了WindowAdapter方便创建侦听器对象而存在。

编辑:

由于WindowListeneris interface,您可以在您的 JFrame 子类中实现它。

public class MainWindow extends JFrame implements WindowListener {
    // this is ok
}
public class MainWindow extends JFrame, WindowAdapter {
    // this is not allow
}

但是你不能用WindowAdapter.

于 2012-05-06T11:20:32.247 回答
8

你可以用任何一种方法做任何事情,但是如果你从界面开始,你的代码将会有很多样板。我相信您在尝试时注意到了这一点。关于实例化等的陈述是一种非常复杂的说法,并且术语有很多混淆。你可以写

c.addWindowListener(new WindowListener() {
  @Override public void windowActivated(WindowEvent arg0) { }
  @Override public void windowClosed(WindowEvent arg0) { System.exit(0); }
  @Override public void windowClosing(WindowEvent arg0) { }
  @Override public void windowDeactivated(WindowEvent arg0) { }
  @Override public void windowDeiconified(WindowEvent arg0) { }
  @Override public void windowIconified(WindowEvent arg0) { }
  @Override public void windowOpened(WindowEvent arg0) { }
});

或者你可以写

c.addWindowListener(new WindowAdapter() {
  @Override public void windowClosed(WindowEvent arg0) { System.exit(0); }
});

在这两种情况下,您都没有实例化,或者——您正在创建实现WindowListener/ extend的匿名类。但是当你直接实现接口时,你被迫实现所有方法,而当你扩展适配器类时,你只能重写你需要的。该类已经具有您必须在案例中编写的这些空实现。WindowAdapterWindowListenerWindowAdapterListener

于 2012-05-06T11:21:37.833 回答
0

有几个适配器类,例如 MouseAdapter、KeyAdapter、WindowAdapter 可以扩展,从而避免编写您实际上不需要的方法。

接口的问题是你必须写出所有你不需要的方法。适配器类可以进一步被子类化,作为覆盖所需方法的一种方式。

http://www.cafeaulait.org/course/week7/19.html

于 2012-05-06T11:38:41.260 回答
0

当您计划使用大多数接口方法时,将使用侦听器。当您只需要使用一些方法时,适配器会更好 b/c 您不必覆盖其余方法。

于 2012-05-06T15:20:05.913 回答
0

其他答案中没有解决另一个方面:API 演变。提供适配器类(也就是接口的空实现或默认实现)可以减少在接口中引入新方法的痛苦。如果 API 仅提供接口,则客户端将被迫实现它们,如果向接口添加新方法,则所有实现类都将中断。但是,如果提供了默认实现,那么客户端就有机会扩展那些,除了方便之外,还可以帮助他们升级到更新的 API 版本。使用Java 8 默认/空实现的默认方法变得不那么重要了,但它们在旧版本中可能很方便。

于 2016-12-19T09:52:18.257 回答