kirilv kirilv - 4 months ago 17
Java Question

Calling super method from within an anonymous inner class inside the overriden method

Imagine we have a class

class A {

public void m() {
System.out.println("A - > m()");
}
}


and I want to override the method m() on class creation without making a second subclass B to extend A.

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

@Override
public void m() {
System.out.println("Override - > m()");
new Thread(new Runnable() {

@Override
public void run() {
// I want to be able to call the super method.
// This is illegal!
A.super.m();
}
}).start();
}
};
a.method();
}


Currently my solution is to create a private method that calls the super.m()

A a = new A() {

private void superMethod() {
super.m();
}

@Override
public void m() {
System.out.println("Overrided - > m()");
new Thread(new Runnable() {

@Override
public void run() {
superMethod();
}
}).start();
}
};
a.m();


I want to know why I am not able to write A.super.m() and is there another way to perform this task.

Answer

I want to know why I am not able to write A.super.m()...

This is because A is in fact not a directly enclosing class. The directly enclosing class of the Runnable is new A() { ... } which is an anonymous subclass of A.

In other words, if you would have had

class A extends Base {
    new Runnable() { ... }
}

then A.super would have worked, but now you have

class <Anonymous subclass of A> extends A {
    new Runnable() { ... }
}

which means that something like A.super isn't possible, since there's no syntax for <Anonymous subclass of A>.super.m.

...and, is there another way to perform this task.

The way you've solved it is reasonable in my opinion. Another way would be to create a local subclass of A (just to introduce an identifier to use in ____.super.m) as follows:

public static void main(String[] args) {

    class SubA extends A {
        @Override
        public void m() {
            System.out.println("Override - > m()");
            new Thread(new Runnable() {

                @Override
                public void run() {
                    SubA.super.m();
                 // ^^^^ we now have a name of the directly enclosing class
                }
            }).start();
        }
    }
    A a = new SubA();
    a.m();
}
Comments