Java “new” keyword in parameter

2019-06-17 05:22发布

问题:

I've been looking through a lot of OOP Design Patterns lately, and I've run into some strange things I've never seen before:

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!");
    }
}); 

Specfically, what does this do (eg. what does the "new" keyword do here)?:

    button.addSelectionListener(new SelectionAdapter() {

Second question:

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

This is a snippet from an observer design pattern. To my new understanding, the name.propertyChange(...) creates an object of PropertyChangeEvent and through Java's observer pattern implementation, automatically notifies the observers by sending this new object's information to the observers (or something very similar to this). Is this correct?

回答1:

Here, the new keyword is creating an anonymous class.

This is useful when you need a listener to perform some action, and you'd like to keep your code grouped together, and/or the class is "one-off", meaning it has no use elsewhere.

Here's a link to sun's tutorial on anonymous classes. All the normal rules of classes apply. You need to implement abstract methods, or all methods when creating an interface.

Scope is a little different as you can access variables declared in the class your anonymous class is nested within. However, you can't access local variables from an anonymous class unless those local variables are declared final. For instance:

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);
    }
});

If someString were declared in more global scope, this would not be the case.

To your second question:

Yes. You are correct, that's what's happening in the snippet. Notice a new PropertyChangeEvent is being created every time? This is so listeners appearing earlier in the list don't modify the PropertyChangeEvent for items appearing later in the list.



回答2:

First of all, this is a Java-specific syntax: there is no comparable syntax in C#, where you must either create an anonymous class extending object, or create an instance of a named class.

In Java this syntax lets you create an anonymous subclass of SelectionAdapter, overriding any methods as you see fit. This is equivalent to creating a named class that extends SelectionAdapter, overriding any methods as you do in the curly braces following the SelectionAdapter() constructor call, and then using the name of that derived class in the call of addSelectionListener. The only difference is that such derived class would have a name, while the anonymous class from your example does not have a name * available to programmers.

* Internally anonymous classes do have names: you can see them if you look at the list of class files generated by the Java compiler. Files with dollar signs and numbers in their names correspond to anonymous classes.



回答3:

The new keyword is creating an anonymous object.

This is useful, when you want to create a instance that only use once.



标签: java oop