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.)
Related
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
I have written following code. Can I access (non-static) method m1() of class NestedClass2??
class OuterClass
{
static class NestedClass
{
static class NestedClass1
{
class NestedClass2
{
void m1()
{
System.out.println("Non-static method of NestedClass2");
}
}
}
}
}
In order to invoke NestedClass2.m1() from another, independent class (in this example I invoke it from Main) you need to create instances of NestedClass1 and NestedClass2.
In the below example, take a look on how to create a non-static class instance of an inner class (nc1.new NestedClass2()) versus how to create a static instance of an inner class (new OuterClass.NestedClass.NestedClass1()).
public class Main {
public static void main(String[] args) {
OuterClass.NestedClass.NestedClass1 nc1 = new OuterClass.NestedClass.NestedClass1();
OuterClass.NestedClass.NestedClass1.NestedClass2 nc2 = nc1.new NestedClass2();
nc2.m1();
}
}
To instantiate an inner class, we must first instantiate its enclosing
class. Then, create the inner object within the outer object with this syntax:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
So,
Create instance of NestedClass1 first.
Create instance of NestedClass2 with above given syntax.
class AnyOtheClass {
public static void main(String args[])
{
OuterClass.NestedClass.NestedClass1 objNestedClass1= new OuterClass.NestedClass.NestedClass1();
OuterClass.NestedClass.NestedClass1.NestedClass2 objNestedClass2= objNestedClass1.new NestedClass2();
objNestedClass2.m1();
}
}
I have the following problem. Two nested anonymous types. I want to access "this" reference of the outer anonymous class inside the most inner class. Usually if one has anonymous nested class in a named outer class (lets call it "class Outer") he/she would type inside the nested class Outer.this.someMethod(). How do I refer the outer class if it's anonymous ?
Example Code:
public interface Outer {
void outerMethod();
}
public interface Inner {
void innerMethod();
}
...
public static void main(String[] args) {
...
new Outer() {
public void outerMethod() {
new Inner() {
public void innerMethod() {
Outer.this.hashCode(); // this does not work
} // innerMethod
}; // Inner
} // outerMethod
}; // Outer
...
} // main
The error I get is
No enclosing instance of the type Outer is accessible in scope
I know that I can copy the reference like this:
final Outer outerThisCopy = this;
just before instantiating the Inner object and then refer to this variable. The real goal is that I want to compare the hashCodes of outerThisCopy and the object accessed inside the new Inner object (i.e the Outer.this) for debugging purposes. I have some good arguments to think that this two objects are different (in my case).
[Context: The argument is that calling a getter implemented in the "Outer" class which is not shadowed in the "Inner" class returns different objects]
Any ideas how do I access the "this" reference of the enclosing anonymous type ?
Thank you.
You cannot access an instance of anonymous class directly from inner class or another anonymous class inside it, since the anonymous class doesn't have a name. However, you can get a reference to the outer class via a method:
new Outer()
{
public Outer getOuter()
{
return this;
}
public void outerMethod()
{
new Inner()
{
public void innerMethod()
{
getOuter().hashCode();
}
};
}
};
Oracle documentation(in below link) says that:
Non-static nested classes (inner classes) have access to other members
of the enclosing class, even if they are declared private.
But in below example I created an object objin (of inner class) and it couldn't access any of the method or variable of its enclosing outer class. Below is the code, could you any one clarify on the same?
http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
package Package_1;
public class Outer {
int k;
public void Multiply()
{
System.out.println("inside outer class' method multiply");
}
public class Inner {
int l;
public void Division()
{
System.out.println("inside inner class' method Divison");
}
}
}
Class with Main method
package Package_1;
public class D {
public static void main(String[] args) {
Outer objout = new Outer();
objout.k = 5;
objout.Multiply();
Outer.Inner objin = objout.new Inner();
objin.l = 7;
objin.Division();
}
}
With objin object I couldn't access that Multiple method in its enclosing class.
I see your "privates"!
From the code of the non-static nested class (inner class) you have access to both public and private members of the enclosing class.
But it's your "privates", not mine!
This is what you're thinking when you try do objin.Multiply(): you are accessing Multiply() as though it's a member of the inner class, but it's not. Remember, you can see it from within the code of the inner class, but it will not be exposed as though it's yours.
This is what the specification says
public class Outer{
private int x;
private void method(){
}
public void publicMethod(){}
public class Inner{
//has access to even private properties of x
method(); //can be called
//NOTE: Only has ACCESS and does not INHERIT those methods
}
}
What you are trying is to access the publicMethod() with the instance of Inner, which does not have any method of that name.
THE CRUX:
The non-static nested classes just has the access to all properties and methods of container class, but does not inherit those methods.
objin.Multiply() cannot work as the crux explains that Multiply() is defined on Outer and not Inner, so there is no method Multiply() on Inner
The documentation doesn't say that you can access to fields and methods of the outer class by using a reference to the inner class. So you can't do
objin.Multiply();
because Multiply is not a method of Inner. What you can do is:
public class Inner {
int l;
public void Division()
{
System.out.println("I can access the field k in outer: " + k);
System.out.println("I can access the method Multiply in outer (even if Multiply was private): ");
Multiply();
// which is a shortcut for
Outer.this.Multiply();
}
}
PS: please respect the Java naming conventions. Methods start with a lowercase letter.
You are trying to access the method by using instance of the Inner class object. It can be accessed outside only by Outer class method. You can call the method inside the class definition of the Inner class directly but not by using the instance of inner class. if you still want to do this try :
package Package_1;
public class Outer {
int k;
public void Multiply()
{
System.out.println("inside outer class' method multiply");
}
public class Inner {
int l;
public void Division()
{
System.out.println("inside inner class' method Divison");
}
public void Multiply() {
Outer.this.Multiply(); //Outer class method.
}
}
}
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.