1

When defining extra methods (that do not override the super class methods) in an Anonymous Inner Class the code compiles fine without any issues but if I try to call the extra method it throws an error. So is it only possible to override methods in the sub class when extending with an anonymous inner class? If it is so can anyone please explain me why?

Here's what my code looks like

class SomeClass {

    public static void main(String[] args) {
        SomeOtherClass a = new SomeOtherClass() {

            @Override 
            public void methodFromSuperClass() {

                System.out.println("Method from super class!");
            }

            public void subClassMethod() {
                System.out.println("Sub class method");
            }

        };

        a.methodFromSuperClass(); //This works fine

        a.subClassMethod(); // But calling this extra method throws an error
        
    }
}

This is the error that I'm getting

 SomeClass.java:20: error: cannot find symbol
      a.subClassMethod();
      ^
      symbol:   method subClassMethod()
      location: variable a of type SomeOtherClass
    1 error
ansme
  • 413
  • 2
  • 11
  • 1
    Your variable `a` is of type `SomeOtherClass`. It seems as if this type simply does not have the method `subClassMethod`. So the compiler is correct. Adding a public member does not make much sense because you can't access it. – Seelenvirtuose Apr 24 '21 at 12:46
  • 1
    You might want to take a look at the [Official Java Doc on Anonymous Inner Classes](https://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html#accessing). Methods can be added in your class, the catch is that it is only accessible within the scope of the class. – Frederic Perron Apr 24 '21 at 13:05
  • @Seelenvirtuose My bad I confused it with `Dynamic Method Dispatch` I thought calling a method which is not overridden would work the same way, But now it seems that it only works with overridden methods. – ansme Apr 24 '21 at 14:24

2 Answers2

3

This situation is exactly the same as if the anonymous class had a name:

class SomeOtherClass {
    public void methodFromSuperClass() { }
}

class Subclass extends SomeOtherClass {
    @Override 
    public void methodFromSuperClass() {

        System.out.println("Method from super class!");
    }

    public void subClassMethod() {
        System.out.println("Sub class method");
    }    
}

And you did:

SomeOtherClass a = new Subclass();
a.subClassMethod();

Wouldn't you agree that you shouldn't be able to call subClassMethod here? After all, the compiler knows that a is of type SomeOtherClass, but not which subclass of SomeOtherClass it is. It doesn't analyse your code that far back to see that you actually assigned an instance of Subclass to it.

The situation with anonymous classes is basically the same. It's just that this time, the subclass doesn't have a name in your code, but it's still a subclass, and the same reasoning that "the compiler doesn't analyse your code that far back" applies.

Since the anonymous subclass has no name, you can't do something like Subclass a = new Subclass(); as in the named subclass example, but since Java 10, you can do:

var a = new SomeOtherClass() { ... };

var lets the compiler infer the type of the variable for you without you saying the type name. The compiler will infer the anonymous subclass as the type for a, and this will allow you to do:

a.subClassMethod();

Finally, it is totally allowed to declare extra members in anonymous classes - it's just rather hard to access them from anywhere other than inside the anonymous class, or the local scope, because the anonymous class has no name. Declaring extra members is still sometimes useful though, because you can access them in the overridden methods for example.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • It seems I confused it with the `Dynamic Method Dispatch`, Because in that situation if the method is overridden in the sub class then even if the variable is of type `super` at runtime sub class's overridden method is called, So does this mean that the compiler only analyzes the code a little deeper for overridden methods? – ansme Apr 24 '21 at 14:31
  • @ansme No, overridden methods are also declared in the superclass, so the compiler can see that calling `methodFromSuperClass` is safe just by looking at `a`'s type, rather than the type of the instance that you have put in it. `a`'s type is a constant thing, but the type of instance in `a` requires a lot more analysis, and is impossible to know without running the code most of the time. The compiler could also just _not_ check whether the call is safe, and let it crash at runtime, but Java is not designed that way. See also [this](https://stackoverflow.com/q/37853463/5133585). – Sweeper Apr 24 '21 at 14:39
  • Thank you so much for the brief explanation its much clearer now! :D – ansme Apr 24 '21 at 16:57
1

Your assumption is correct. It is not possible to call the unoverridden method this way. Consider an example where you have declared an interface and instantiated it with a concrete class, then you still only have access to the methods defined in the interface and not in the class.

public interface MyInterface{
  public void someMethod();
}
public class MyImpl implements MyInterface{
  //someMethod() implementation
  // ...
  // newMethod()
  public void newMethod(){
    //some implementation
  }
}
public class Main{
  public static void main(String[] args){
    MyInterface inter = new MyImpl();
    inter.someMethod(); // this call is ok
    inter.newMethod();  // this call leads to a Symbol not found Exception, 
                        // because MyInterface has no method named newMethod...
  }
}

Hope it is now clearer what is meant by this

H4x9r
  • 199
  • 10