Home > Back-end >  Cannot use '<>' due to non-private method which doesn't override or implement a
Cannot use '<>' due to non-private method which doesn't override or implement a

Time:05-16

I have the below specified behavior.

interface ValueEditorPopupView<T> {
  void setValue(T value);

  void setApplyEnabled();
}

abstract class ValueEditorPopup<T> implements ValueEditorPopupView<T> {
  @Override
  public void setApplyEnabled() {
    System.out.println("In ValueEditorPopup.setApplyEnabled()");
  }
}

class ListEditorTextField {
  private final ValueEditorPopup<String> popup;

  ListEditorTextField() {
    popup = new ValueEditorPopup<>() {
      @Override
      public void setValue(String value) {
        System.out.println("In Anonymous Class impl setValue()");
      }

      // When I add a method that is NOT defined in the abstract class/interface
      // I get an error for using the diamond operator in the class declaration above
      // "Cannot use '<>' due to non-private method which 
      // doesn't override or implement a method from a supertype"
      // This error clears if I explicitly specify `new ValueEditorPopup<String>(){}`
      // in the anonymous class instantiation or 
      // add `getValues` to the abstract class/interface.
      public void getValues() {}
    };
  }

}

As noted in a comment in the code above, when I add a method that is NOT defined in the abstract class/interface I get an error for using the diamond operator in the class declaration above:

"Cannot use '<>' due to non-private method which doesn't override or implement a method from a supertype"

This error clears if I explicitly specify new ValueEditorPopup<String>(){} in the anonymous class instantiation or add getValues to the abstract class/interface.

I don't understand why the error is being caused and why adding those methods/types fixes it. Not sure what I am missing here.

CodePudding user response:

This is by design and is specified in JLS §15.9.5:

If a class instance creation expression with a ClassBody uses a diamond (<>) for the type arguments of the class to be instantiated, then for all non-private methods declared in the ClassBody, it is as if the method declaration is annotated with @Override.

Your public getValue method does not override anything in the superclass, so there is an error because of the implicitly added @Override.

The justification for this is:

When <> is used, the inferred type arguments may not be as anticipated by the programmer. Consequently, the supertype of the anonymous class may not be as anticipated, and methods declared in the anonymous class may not override supertype methods as intended. Treating such methods as if annotated with @Override (if they are not explicitly annotated with @Override) helps avoid silently incorrect programs.

My interpretation of that is, when you declare public methods in a anonymous class, it is most likely to override a method, so the compiler implicitly puts @Override on all your public methods when you use <>. This is to make sure that the methods you wrote do override the methods in the superclass, since without writing down the type parameter explicitly, the compiler might infer an unexpected type and the signatures you wrote doesn't actually override the methods in the superclass. (I sadly can't think of a good example of this off the top of my head)

There is rarely a need to declare public methods in anonymous classes without overriding. If you want to declare a method, just declare it as a private method - you can't call it from outside anyway unless you assign the new expression to a var, and that is very rare.

  • Related