Anonymous Inner Class Working? - java

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

Related

Why can I access overridden subclass methods from the superclass? [duplicate]

This question already has answers here:
Java superclass calls subclass method
(5 answers)
Closed 1 year ago.
Why does method() call the overridden subclass method2 instead of method2 in the BaseClass?
public class BaseClass {
public void method(){
System.out.println("method() called");
method2();
}
public void method2(){
System.out.println("method2() called");
}
}
public class ChildClass extends BaseClass {
public void method2(){
System.out.println("method2() from BaseClass");
}
}
public class Main {
public static void main(String[] args) {
ChildClass obj = new ChildClass();
obj.method();
}
}
This is the concept of Runtime polymorphism (Dynamic Method Dispatch). Because you are assigning the object (instance) of ChildClass to obj reference variable, it will call the method of child class.
Always the method of the class whose instance is created gets called first. If that method is not present in that particular child class, then the parent's inherited method gets called.
If you come from the C++ corner:
all instance methods (non-static) in Java are virtual.
All class methods (static) are NOT.
This is why your case happens.
This is also, why the Java compiler will complain (warn) that if you access a static method via an object, that you should call via the distinct class, because calls to the "static method of a object" could be ambiguous, because it could be two static methods with the same signature that get called.
Extending your Example:
package stackoverflow.staticcalls;
public class BaseClass {
public void method() {
System.out.println("method() called");
method2();
}
public void method2() {
System.out.println("method2() called");
}
static public void sayHello() {
System.out.println("BaseClass.sayHello()");
}
}
and
package stackoverflow.staticcalls;
public class ChildClass extends BaseClass {
public void method2() { // compiler warning: The method method2() of type ChildClass should be tagged with #Override since it actually overrides a superclass method
System.out.println("method2() from BaseClass");
}
public void originalCallToBaseMethod2() {
super.method2(); // will run BaseClass.method2()
}
static public void sayHello() {
System.out.println("ChildClass.sayHello()");
}
}
and
package stackoverflow.staticcalls;
public class Main {
public static void main(final String[] args) {
final ChildClass obj = new ChildClass();
System.out.println("\nCalling obj.method(); ...");
obj.method();
System.out.println("\nCalling obj.sayHello(); ...");
obj.sayHello(); // compiler warning: The static method sayHello() from the type ChildClass should be accessed in a static way
System.out.println("\nCalling ChildClass.sayHello(); ...");
ChildClass.sayHello(); // the proper call
System.out.println("\nCalling BaseClass.sayHello(); ...");
BaseClass.sayHello(); // but you can also explpicitly call the other method
System.out.println("\nCalling obj.originalCallToBaseMethod2(); ...");
obj.originalCallToBaseMethod2(); //
}
}
Here you see the examples to what I said.
Note: In the last call in Main.main() we still can call BaseClass.method2(), but not directly. We have to be within ChildClass to do that, and it's done via the super keyword/reference.
A little off-topic note, to complete addressing patterns:
If you're inside an inner class and need to call to a overshadowed name in the outer class, you can use Outer.this.method():
package stackoverflow.staticcalls;
import stackoverflow.staticcalls.OuterInner.Outer.Inner;
public class OuterInner {
class Outer {
void method() {
System.out.println("OuterInner.Outer.method()");
}
class Inner {
void method() {
System.out.println("OuterInner.Outer.Inner.method()");
}
void callOuter() {
Outer.this.method();
}
}
}
public static void main(final String[] args) {
final OuterInner oi = new OuterInner();
final Outer outer = oi.new Outer();
final Inner inner = outer.new Inner();
System.out.println("\nCalling inner.method(); ...");
inner.method();
System.out.println("\nCalling inner.callOuter(); ...");
inner.callOuter();
}
}

Ways to call method local inner class from outside [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
public class OuterMain {
public static void main(String[] args) {
Outer outer = new Outer();
outer.m2();
}
}
class Outer {
public void m1() {
class Inner {
void display() {
System.out.println("msg is displayed");
}
}
Inner inn = new Inner();
//cannot write code to call display() here
}
public void m2() {
//inner.display();
}
}
Above is the code block where there is a method local inner class. The display method inside the inner class prints a message. The main class creates an instance of Outer and calls m2(). I was asked to do modification, apply any concept in java but the task is to call the Inner class' display() method from m2(). Only restriction is that the method cannot be made static.
One thing you can do is use a private interface and make Inner implement it, thus enabling m2() to return an object with a display() method that can be called elsewhere in the same outer class
class Outer {
public Displayable m1() {
class Inner implements Displayable {
#Override
public void display() {
System.out.println("msg is displayed");
}
}
return new Inner();
}
private interface Displayable {
void display();
}
public void m2() {
m1().display();
}
}
There are three issues here
The type Inner is not visible to m2()
The instance of Inner created in m1() is not visible to m2()
The method m1() is never invoked.
The purpose of local classes is precisely to reduce the visibility of the class and its instances and to avoid creating the instances when the method has not been invoked. Even the initialization of Inner should be deferred until the method m1() creates the first instance of it.
A solution not perverting those properties would be
class Outer {
private Runnable accessor;
public void m1() {
class Inner {
void display() {
System.out.println("msg is displayed");
}
}
Inner inn = new Inner();
accessor = inn::display;
}
public void m2() {
m1();
accessor.run();
}
}
Here, m1() doesn't invoke display but provides access to it using a standard interface, without giving away any information about its internals. m2() invokes the method m1() to get the access followed by invoking the standard interface method.
In Java, we can write a class within a method and this will be a local type. Like local variables, the scope of the inner class is restricted within the method.
A method-local inner class can be instantiated only within the method where the inner class is defined. The following program shows how to use a method-local inner class
instantiate the class at proper point.
I will show you the code*
package com;
public class Outer{
public void m1() {
class Inner {
public void display(){
System.out.println("display from inner class");
}
}// end of inner class
// Accessing the inner class
Inner inner = new Inner();
inner.display();
}//m1 ends here
public static void main(String[] args) {
Outer outer=new Outer();
outer.m1();
}
}
With the help of interface the inner class method can be access as per your requirement :
class OusterMain{
public static void main(String[] args) {
OuterClass oc = new OuterClass();
oc.methodTwo();
}
}
class OuterClass {
public InnerInterface methodOne() {
class InnerClass implements InnerInterface{
#Override
public void display() {
System.out.println("Print message.");
}
}
// this reference is used to call display() method inside methodTwo()
return new InnerClass();
}
private interface InnerInterface{
void display();
}
public void methodTwo() {
methodOne().display();
}
}
Using reflection you can achieve this goal easily.
Here com.problem.solution is my package name. Replace it with your package name.
Get the outer and inner class object associated with the class or interface with the given string name.
Like - forName("com.problem.solution.Outer");
Then try to access inner class using - Class.forName("com.problem.solution.Outer$1Inner");
In java reflection, you can access any inner class using OuterClass$1InnerClass this type of syntax.
Then construct object, then pick your desired method and then invoke that method.
Complete code:
//package com.problem.solution;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class OuterMain {
public static void main(String[] args) {
Outer outer = new Outer();
outer.m2();
}
}
class Outer {
public void m1() {
class Inner {
void display() {
System.out.println("msg is displayed");
}
}
Inner y = new Inner();
}
public void m2() {
try {
Class<?> enclosingClass = Class.forName("com.problem.solution.Outer");
Object enclosingInstance = enclosingClass.newInstance();
Class<?> innerClass = Class.forName("com.problem.solution.Outer$1Inner");
Constructor<?> ctor = innerClass.getDeclaredConstructor(enclosingClass);
Object innerInstance = ctor.newInstance(enclosingInstance);
Method someMethod = innerInstance.getClass().getDeclaredMethod("display");
someMethod.setAccessible(true);
someMethod.invoke(innerInstance);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Output:
msg is displayed

Nested Interafce in java

This is my java code:
class A {
interface That {
void show();
}
}
class B implements A.That {
public void show() {
System.out.println("Hi");
}
}
public class MainClass {
public static void main(String args[]) {
A obj = new A();
obj.That object = new B();
object.show();
}
}
Since A is a class (not abstract) we can create its instance and than we can use members of that instance. Now interface is member so obj.That should work but javac says that obj.That is not package. Why?
Interfaces are always static when nested in a class. You should therefore access your interface declaration as A.That, not obj.That.

Java: Get super class from an anonymous class

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

Instances of classes

Does a non-static method create an instance of the class in which it is declared? If not why this code works?
import java.awt.*;
public class Main extends Frame {
public Main () {
//super keyword needs an istance of the class don't it?
super ("My frame");
super.setSize (200,100);
}
public static void main (String [ ] args) {
new Main();
}
}
If a non-static method creates an instance of the class the next code should work...
import.java.applet.*;
public class Main extends Applet {
public void print () {
System.out.println ("Hi");
}
public void init () {
this.print();
}
}
A non-static method can only be accessed in the context of an instance that already exists.
public class Foo {
public static void someStaticMethod() { /* ... */ }
public void someNonStaticMethod() { /* ... */ }
}
Elsewhere:
Foo.someStaticMethod(); // this works
Foo.someNonStaticMethod(); // this DOESN'T work
Foo foo = new Foo();
foo.someNonStaticMethod(); // but this does
Within a non-static method, you have access to an instance by default (implicitly), or can refer to it explicitly using the this keyword. In your example:
public class Main extends Frame {
public Main () {
//super keyword needs an istance of the class don't it?
super ("My frame");
super.setSize (200,100);
}
public static void main (String [ ] args) {
new Main();
}
}
...the instance in question in the call to super is the implicit instance you create with new Main().
Instances of classes in Java are created by calling a constructor using the new keyword:
Main main = new Main();
public void Main () { } however is not a constructor, but a instance method (which, in your example, never gets called).
public class Main {
public static void main(String[] args) {
Main main = new Main(); // create instance
main.Main(); // call method 'Main'
new Main().Main(); // or both at once
}
public Main() {
// this is the (default) constructor
}
public void Main() {
// this is an instance method (whose name 'should' start lowercase
}
}
Does a non-static method create an instance of the class in which it is declared?
No.
why this code works?
Because when such a method is called, it should be called from an already instantiated instance. "this"/"super" refer to the implicit parameter, which is the instance in question (instantiated and passed in from elsewhere, with "new"). If instantiation has not occurred, a NullPointerException will immediately be thrown.
Well actually in the main question I wrote a wrong code (I've been out for all the day and I'm quite tired) anyway it helped me to understand more. Now what about this code
import java.applet.*;
public class Main extends Applet {
//overrides Applet.init ()
public void init () {
//here I use super keyword without creating an istance of the class
super.init ();
//code here...
}
}

Categories

Resources