Java: Get super class from an anonymous class - java

In Java, I use an anonymous class inside a class A which extends B. How can I access to B from this anonymous class? I can't use the keyword super, because this means super class of the anonymous class, not super class of A.
public class A {
void foo() {
System.out.println("Good");
}
}
public class B extends A {
void bar() {
Runnable r = new Runnable() {
#Override
public void run() {
foo(); // Bad: this call B.foo(), not A.foo()
// super.foo(); // Bad: "Method foo is undefined for type Object"
}
};
r.run();
}
#Override
void foo() {
System.out.println("Bad");
}
}

In run, you could change foo() to B.super.foo(); when I changed that and then ran B.bar() I get Good.

In such a case, you need to qualify this to capture the outer class, B
B.this.foo()
Or, in your case, as you want the super class, use
B.super.foo()
Relevant parts of Java Language Spec:
Qualified this
Accessing superclass members with super

Please call as fallows:
B.super.foo();
After this change B class looks as follows:
public class B extends A {
public static void main(String[] args) {
new B().bar();
}
void bar() {
Runnable r = new Runnable() {
#Override
public void run() {
B.super.foo(); // this calls A.foo()
}
};
r.run();
}
#Override
void foo() {
System.out.println("Bad");
}
}

Related

How to force derived class to call super class method at multiple layers?

I am trying to find the most elegant way to allow a child and parent to react to an event initiated by the grandparent. Here's a naive solution to this:
abstract class A {
final public void foo() {
// Some stuff here
onFoo();
}
protected abstract void onFoo();
}
abstract class B extends A {
#Override
final protected void onFoo() {
// More stuff here
onOnFoo();
}
protected abstract void onOnFoo();
}
class C extends B {
#Override
protected void onOnFoo() {
// Even more stuff here
}
}
So basically, I'm trying to find the best way to allow all related classes to perform some logic when foo() is called. For stability and simplicity purposes I prefer if it is all done in order, although it's not a requirement.
One other solution I found involves storing all the event handlers as some form of Runnable:
abstract class A {
private ArrayList<Runnable> fooHandlers = new ArrayList<>();
final public void foo() {
// Some stuff here
for(Runnable handler : fooHandlers) handler.run();
}
final protected void addFooHandler(Runnable handler) {
fooHandlers.add(handler);
}
}
abstract class B extends A {
public B() {
addFooHandler(this::onFoo);
}
private void onFoo() {
// Stuff
}
}
class C extends B {
public C() {
addFooHandler(this::onFoo);
}
private void onFoo() {
// More stuff
}
}
This method is certainly preferable to the first. However I am still curious if there is a better option.
Have you considered the Template Method pattern? It works well to define a high level method that delegates to derived types to fill-in the gaps.
What about this by calling the super method?
class A {
void foo() {
System.out.println("Some stuff here");
}
}
class B extends A {
#Override
void foo() {
super.foo();
System.out.println("More stuff here");
}
}
class C extends B {
#Override
void foo() {
super.foo();
System.out.println("Even more stuff here");
}
}

Anonymous Inner Class Working?

As I have gone through some of the programming sites which explains anonymous inner class in java.
But, I still have doubts that how it really works and on the conclusions which I made below.
Here is code :
public class Implementing {
public static void main(String[] args) {
SuperClass a = new SuperClass() { // ... 1st
public void call () { // ... 2nd
System.out.println("Method call");
}
public void call2 () { // creating new method in anonymous inner class
System.out.println ("New call2 Method in Anonymous Class");
}
};
a.call(); // ... 3rd
try {
a.getClass().getMethod("call2",null).invoke(a,null); // ... 4th
} catch (Exeception e) {
System.out.println(e);
}
}
}
class SuperClass {
public void call() {
System.out.println("Super Class");
}
}
What I understand is this :
At 1st :-
Anonymous inner class is sub-class.
we are creating instance of anonymous inner class as well as we
are extending the class SuperClass.
we are running constructor of SuperClass, but we created object
of anonymous class of type SuperClass.
polymorphism at work.
Actually, we are doing this at 1st :
* 1. anonymousClass extends SuperClass
* 2. anonymousClass a = new SuperClass()
* 3. { }; // our anonymous class field
At 2nd : - overrides SuperClass call Method().
At 3rd : - calling call() Method by object 'a'.
At 4th : - accessing new method call2() Method in anonymous inner class.
So, my these conclusions are right or wrong ? If wrong why they are wrong ? Please Explain.
Your code creating an Anonymous Class:
public static void main(String[] args) {
SuperClass a = new SuperClass() { // ... 1st
public void call() {
System.out.println("Method call");
}
public void call2() {
System.out.println("New call2 Method in Anonymous Class");
}
};
...
}
is the same as this code creating a Local Class:
public static void main(String[] args) {
class LocalClass extends SuperClass {
public void call() {
System.out.println("Method call");
}
public void call2() {
System.out.println("New call2 Method in Anonymous Class");
}
}
SuperClass b = new LocalClass();
...
}
except that the class is unnamed, aka anonymous.
Since you're doing this from a static method, and you're not using any local variables, they are both the same as this Static Nested Class:
static class NestedClass extends SuperClass {
public void call() {
System.out.println("Method call");
}
public void call2() {
System.out.println("New call2 Method in Anonymous Class");
}
}
If you look at the compiled .class files, you'll see they are all just classes:
SuperClass.class <-- Your superclass
Implementing.class <-- Your main class
Implementing$1.class <-- Anonymous class
Implementing$1LocalClass.class <-- Local class
Implementing$NestedClass.class <-- Nested class

Calling super method from within an anonymous inner class inside the overridden 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.m();
}
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 if there another way to perform this task.
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();
}
Writing A.super.m(), suppose that A has a superclass with a m method.
But in your code, you don't specify a superclass, and by default, the only superclass you have is Object.
But Object class doesn't have a 'm' method, so you could not call it.
A good way to do something like that is to use design pattern, like decorator.
I don't think there would be a simpler way to do it other than the way you already have it.
The problem is that the anonymous class A itself (not the base class A) cannot be referenced inside the Runnable class. The anonymous class is represented as something like package.A$1 when compiled to its own class file. For example, when you call superMethod inside the run of the thread, the following bytecode is executed:
getfield mypackage/Test$1$1/this$1 Lmypackage/Test$1;
invokestatic mypackage/Test$1/access$0(Lmypackage/Test$1;)V
In order to reference its base class A, there is no reference to this inner class instance so that you call the super.m() expression.

Anonymous classes enclosing instances

I'm reading Joshua Blochs "Effective Java" 2nd edition. Currently I'm at item 22 which describes inner and nested classes but I can't understand what does he mean by this sentence:
Anonymous classes have enclosing instances if and only if they occur
in a nonstatic context.
Can someone give me an example of code and explain what does it exactly do ? I know that if InnerClass is a member of OuterClass its enclosing instance is OuterClass, but in terms of annonymous class it sounds strange to me.
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
System.out.println("hello world");
}
};
}
Here, an anonymous class instance is created from a static context. So it doesn't have any enclosing instance.
public class Foo {
public void bar() {
Runnable r = new Runnable() {
#Override
public void run() {
System.out.println("hello world");
}
};
}
private void baz() {
}
}
Here, an anonymous class instance is created from an instance method. So it has an enclosing instance. The run() method could call baz() or Foo.this.baz(), thus accessing a method from this enclosing instance.
The effect is the same as for non-anonymous inner classes. In essence, it means:
class Outer {
void bar() {
System.out.println("seems you called bar()");
}
void foo() {
(new Runnable() {
void run() {
Outer.this.bar(); // this is valid
}
}).run();
}
static void sfoo() {
(new Runnable() {
void run() {
Outer.this.bar(); // this is *not* valid
}
}).run();
}
}
Because you cannot give the static modifier to anonymous classes, the static property is always inherited from the context.

Explicitly calling a default method in Java

Java 8 introduces default methods to provide the ability to extend interfaces without the need to modify existing implementations.
I wonder if it's possible to explicitly invoke the default implementation of a method when that method has been overridden or is not available because of conflicting default implementations in different interfaces.
interface A {
default void foo() {
System.out.println("A.foo");
}
}
class B implements A {
#Override
public void foo() {
System.out.println("B.foo");
}
public void afoo() {
// how to invoke A.foo() here?
}
}
Considering the code above, how would you call A.foo() from a method of class B?
As per this article you access default method in interface A using
A.super.foo();
This could be used as follows (assuming interfaces A and C both have default methods foo())
public class ChildClass implements A, C {
#Override
public void foo() {
//you could completely override the default implementations
doSomethingElse();
//or manage conflicts between the same method foo() in both A and C
A.super.foo();
}
public void bah() {
A.super.foo(); //original foo() from A accessed
C.super.foo(); //original foo() from C accessed
}
}
A and C can both have .foo() methods and the specific default implementation can be chosen or you can use one (or both) as part of your new foo() method. You can also use the same syntax to access the default versions in other methods in your implementing class.
Formal description of the method invocation syntax can be found in the chapter 15 of the JLS.
This answer is written mainly for users who are coming from question 45047550 which is closed.
Java 8 interfaces introduce some aspects of multiple inheritance. Default methods have an implemented function body. To call a method from the super class you can use the keyword super, but if you want to make this with a super interface it's required to name it explicitly.
class ParentClass {
public void hello() {
System.out.println("Hello ParentClass!");
}
}
interface InterfaceFoo {
public default void hello() {
System.out.println("Hello InterfaceFoo!");
}
}
interface InterfaceBar {
public default void hello() {
System.out.println("Hello InterfaceBar!");
}
}
public class Example extends ParentClass implements InterfaceFoo, InterfaceBar {
public void hello() {
super.hello(); // (note: ParentClass.super could not be used)
InterfaceFoo.super.hello();
InterfaceBar.super.hello();
}
public static void main(String[] args) {
new Example().hello();
}
}
Output:
Hello ParentClass!
Hello InterfaceFoo!
Hello InterfaceBar!
The code below should work.
public class B implements A {
#Override
public void foo() {
System.out.println("B.foo");
}
void aFoo() {
A.super.foo();
}
public static void main(String[] args) {
B b = new B();
b.foo();
b.aFoo();
}
}
interface A {
default void foo() {
System.out.println("A.foo");
}
}
Output:
B.foo
A.foo
You don't need to override the default method of an interface. Just call it like the following:
public class B implements A {
#Override
public void foo() {
System.out.println("B.foo");
}
public void afoo() {
A.super.foo();
}
public static void main(String[] args) {
B b=new B();
b.afoo();
}
}
Output:
A.foo
It depends on your choice whether you want to override the default method of an interface or not. Because default are similar to instance method of a class which can be directly called upon the implementing class object. (In short default method of an interface is inherited by implementing class)
Consider the following example:
interface I{
default void print(){
System.out.println("Interface");
}
}
abstract class Abs{
public void print(){
System.out.println("Abstract");
}
}
public class Test extends Abs implements I{
public static void main(String[] args) throws ExecutionException, InterruptedException
{
Test t = new Test();
t.print();// calls Abstract's print method and How to call interface's defaut method?
}
}

Categories

Resources