7

最近我浏览了很多 OOP 设计模式,并且遇到了一些我以前从未见过的奇怪的事情:

Button button =  new Button(shell, SWT.PUSH);
button.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
    // Handle the selection event
    System.out.println("Called!");
    }
}); 

具体来说,这是做什么的(例如,“new”关键字在这里做什么)?:

    button.addSelectionListener(new SelectionAdapter() {

第二个问题:

private void notifyListeners(Object object, String property, String oldValue, String newValue) {
   for (PropertyChangeListener name : listener) {
      name.propertyChange(new PropertyChangeEvent(this, "firstName", oldValue, newValue));
   }
}

这是来自观察者设计模式的片段。根据我的新理解,name.propertyChange(...) 创建了一个 PropertyChangeEvent 对象,并通过 Java 的观察者模式实现,通过将这个新对象的信息发送给观察者(或类似的东西)自动通知观察者。它是否正确?

4

3 回答 3

23

在这里,new关键字是创建一个匿名类。

当您需要一个侦听器来执行某些操作时,这很有用,并且您希望将代码组合在一起,和/或该类是“一次性的”,这意味着它在其他地方没有用处。

这是 sun关于匿名类的教程的链接。所有正常的课程规则都适用。您需要在创建接口时实现抽象方法或所有方法。

范围有点不同,因为您可以访问在匿名类嵌套的类中声明的变量。但是,您不能从匿名类访问局部变量,除非这些局部变量被声明为 final。例如:

Button button =  new Button(shell, SWT.PUSH);
final String someString = "hello world!";
button.addSelectionListener(new SelectionAdapter() { 
    @Override
    public void widgetSelected(SelectionEvent e) {
        // Handle the selection event
        System.out.println(someString);
    }
});

如果someString在更全局范围内声明,则情况并非如此。

对于你的第二个问题:

是的。你是对的,这就是片段中发生的事情。注意PropertyChangeEvent每次都在创建一个新的?这样一来,列表中较早出现的侦听器就不会修改列表PropertyChangeEvent中稍后出现的 for 项目。

于 2013-08-01T01:46:59.690 回答
4

首先,这是一种特定于 Java 的语法:在 C# 中没有类似的语法,您必须创建一个匿名类扩展object,或者创建一个命名类的实例。

在 Java 中,此语法允许您创建 的匿名子类SelectionAdapter,覆盖您认为合适的任何方法。这等效于创建一个扩展的命名类SelectionAdapter,重写任何方法,就像在构造函数调用之后的花括号中所做的那样SelectionAdapter(),然后在调用中使用该派生类的名称addSelectionListener。唯一的区别是这样的派生类将有一个名称,而您示例中的匿名类没有名称*可供程序员使用。

*内部匿名类确实有名称:如果您查看 Java 编译器生成的类文件列表,您可以看到它们。名称中带有美元符号和数字的文件对应于匿名类。

于 2013-08-01T01:47:26.067 回答
0

new 关键字是创建一个匿名对象。

当您想创建一个只使用一次的实例时,这很有用。

于 2013-08-01T01:58:38.423 回答