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

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

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

How to access anonymous inner class in main method?

How to access the anonymous inner class object in main method. It is giving compile time error saying that "cannot make static reference to non static method". If I am making anonymous inner class as static then I can access ut I want to access without making it static.
How to do that. Please help.
AnonymousInnerClass2.java
abstract class AnonymousInnerClass21
{
abstract void m();
}
public class AnonymousInnerClass2
{
AnonymousInnerClass21 a=new AnonymousInnerClass21()
{
#Override
void m() {
System.out.println("Hello");
}
};
public static void main(String[] args)
{
a.m();
}
}
this is because for accessing inner class (whether its is normal/named class or Anonymous class), you must create object of class in which inner class is defined, you can try below
abstract class AnonymousInnerClass21
{
abstract void m();
}
public class AnonymousInnerClass2
{
AnonymousInnerClass21 a=new AnonymousInnerClass21()
{
#Override
void m() {
System.out.println("Hello");
}
};
public static void main(String[] args)
{
AnonymousInnerClass2 anonymousInnerClass2= new AnonymousInnerClass2 ();//create outer class object
anonymousInnerClass2.a.m(); // access inner class object through outer class object
}
}

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

creating inner class objects with reflection

How do you create an inner class object with reflection? Both Inner and Outer classes have default constructors that take no parameters
Outer class {
Inner class{
}
public void createO() {
Outer.Inner ob = new Inner ();//that works
Inner.class.newInstance(); //<--why does this not compile?
}
}
"If the constructor's declaring class is an inner class in a non-static context, the first argument to the constructor needs to be the enclosing instance; see section 15.9.3 of The Java™ Language Specification."
That means you can never construct an inner class using Class.newInstance; instead, you must use the constructor that takes a single Outer instance. Here's some example code that demonstrates its use:
class Outer {
class Inner {
#Override
public String toString() {
return String.format("#<Inner[%h] outer=%s>", this, Outer.this);
}
}
#Override
public String toString() {
return String.format("#<Outer[%h]>", this);
}
public Inner newInner() {
return new Inner();
}
public Inner newInnerReflect() throws Exception {
return Inner.class.getDeclaredConstructor(Outer.class).newInstance(this);
}
public static void main(String[] args) throws Exception {
Outer outer = new Outer();
System.out.println(outer);
System.out.println(outer.newInner());
System.out.println(outer.newInnerReflect());
System.out.println(outer.new Inner());
System.out.println(Inner.class.getDeclaredConstructor(Outer.class).newInstance(outer));
}
}
(Note that in standard Java terminology, an inner class is always non-static. A static member class is called a nested class.)

Inheriting InnerClass in java

public class InnerClass {
class Inner
{
public void method()
{
System.out.println("Innerclass");
}
}
}
class Sample extends InnerClass.Inner
{
public static void main(String [] arg)
{
Sample s = new Sample(new InnerClass());
s.method();
}
//why is this mandatory???
Sample(InnerClass i) {
i.super();
}
#Override
public void method() {
System.out.println("derived class");
}
}
when i make a class that derives from an innerclass (Innerclass.Inner) default constructor doesn't works. later i came to know that it requires to include a constructor taking Enclosing class reference why is it so?
Non static inner classes in Java have an implicit reference to the enclosing instance. You can solve your problem with:
public class InnerClass {
static class Inner // can make it public too
{
public void method()
{
System.out.println("Innerclass");
}
}
}
Just don't expect to be able to call any methods on InnerClass without a specific instance.
Because non-static inner classes have an implicit member that points back to their outer class, and you can't create an instance of the inner class without giving it that pointer. If you directly create an instance of an inner class, you have to use new outer.Inner() (or it might be outer.new Inner(), I can never remember). But Sample isn't an inner class, it just inherits one, so the outer instance must be passed in its constructor to the base constructor. Thus, it needs to have some instance of outer available, or create it itself.

Categories

Resources