Java 侦听器和适配器之间有什么区别?

Java 侦听器和适配器之间有什么区别?,java,swing,awt,adapter,listeners,Java,Swing,Awt,Adapter,Listeners,我试图区分侦听器和适配器 它们是否几乎相同,但在侦听器中,您必须实现接口中的所有方法,但使用适配器,您可以选择仅实现所需的方法,以便代码更干净、更易于阅读 我还听说适配器只支持一个实现的实例化,而您不能实例化侦听器,我不完全理解这一点 有人能解释一下哪一个更好用,以及你可以用其中一个做但不能用另一个做的事情吗?是接口,它迫使你覆盖所有的方法,而WindowListener的实现则是覆盖方法你有兴趣处理的 WindowListener是一个接口,这意味着您不能实例化WindowListener,而

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

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

我还听说适配器只支持一个实现的实例化,而您不能实例化侦听器,我不完全理解这一点

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

接口
,它迫使你覆盖所有的方法,而
WindowListener的实现则是
覆盖
方法你有兴趣处理的

WindowListener
是一个接口,这意味着您不能实例化
WindowListener
,而
WindowAdapter
是一个具体的类,您可以使用
new
操作符来实例化

当您使用
WindowAdapter
时,当您的类只重写您想要的方法时,代码会更干净。 例如:

窗口事件 窗口适配器 使用适配器时,代码更清晰:

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

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

因此,我建议使用
WindowAdapter
,但不要使用,必须遵循。但是,其中两个API与
WindowAdapter
大致相同,只是为了方便创建侦听器对象

编辑:

由于
WindowListener
interface
,您可以在JFrame子类中实现它

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

但是你不能用
WindowAdapter

做这一切,但是如果你从界面开始,你的代码将会有很多样板文件。我肯定你在尝试时注意到了这一点。关于实例化等的陈述是一种非常复杂的表达方式,术语上有很多混淆。你可以写

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
WindowAdapter
——您正在创建实现
WindowListener
/extend
WindowAdapter
的匿名类。但是,当您直接实现接口时,您必须实现所有方法,而当您扩展适配器类时,您只能覆盖您需要的。该类已经有了您必须在
Listener
案例中编写的空实现。

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

接口的问题是,您必须写出所有不需要的方法。适配器类可以进一步细分为子类,以覆盖所需的方法


当您计划使用大多数接口方法时,将使用侦听器。当您只需要使用其中的几个方法时,适配器会更好,b/c您不必重写其余的方法。

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

谢谢。你介意让我知道“适配器只启用一个实现的实例化,而你不能实例化侦听器”是什么意思吗侦听器接口通常只是一个接口,所以你不能创建一个新的侦听器,你需要为实现这个接口的某个类创建一个新的实例。另一方面,适配器可以直接实例化(如果它们不是抽象的话)——但默认情况下它们通常不做任何事情,因此没有创建它们的实际用例。这是一个非常好的答案。我仍然不明白为什么要实例化适配器类。这项工作何时完成的示例将非常有用。:)如果您正在重用适配器/侦听器来注册到多个对象,这可能是有意义的。例如,您可以使用一个只刷新某些内容的
KeyAdapter
。您希望在几个jtextfield上出现这种行为。。。然后您可以创建一个实例,并将该实例添加到所有实例中,而不是创建多个匿名版本。虽然我也不太清楚Pau Kiat Wee的话是什么意思……但我认为您的第二个代码示例的意思是创建
WindowAdapter
的实例,而不是
WindowListener
,这是唯一澄清我对差异理解的答案!非常感谢你!
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); }
});