3

I was randomly writing a code & encountered a problem: how to instantiate class E (shown below) which is defined within an anonymous inner class; like:

 A c = new A() {
   class E{ //Statements
     }
 };
GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • Why not declare the anonymous class outside of A? You'd be able to use it inside A in that case. – Anish Goyal Mar 23 '17 at 18:37
  • no because IT IS AN INNER ANONYMOUS CLASS to instanciate something he must be seen ( let say outer ) and it must be know (not really but perhaps all the time ) but is anonymous , So NO – Mohammed Housseyn Taleb Mar 23 '17 at 18:41
  • @MohammedHousseynTaleb: please, be more clear. – Suyash Jain Mar 23 '17 at 18:47
  • sorry for my bad english, but what I tried to say is about logic, instantiation is About visibility, an inner Anonymous class is not visible ( let say scoop ) outside his parent class in your case A, more we have to pay attention that your example is more harder because your anonymous inner class is only a property ( mathematically said ) of your instance new A(). so try to be humanly a class and you want to call for my inner class that is hiden in my pocket knowing that this class somebody unknown has made it there ... this is somehow philosophical so try read more about OO paradigm. – Mohammed Housseyn Taleb Mar 23 '17 at 18:59
  • @SuyashJain as answered below it needs a work around since to acces it it needs an identifier, thus i proposed a solution in my answer below for accesing it by using an interface instead – Mikenno Mar 23 '17 at 19:18
  • Update: you got me curious; I updated my answer ... with some reflection code that instantiates an inner class of an anonymous inner class. – GhostCat Mar 23 '17 at 19:36

1 Answers1

2

You can't write a program that uses an ordinary call to new to do that: in order for a class to be instantiated, it must have a name. Anonymous inner classes, as that term implies, do not have a name.

Thus a class that exists within that anonymous inner class also has no name; thus it can not be instantiated outside of that anonymous inner class.

But you can use reflection. See my Test.java:

import java.util.*;
import java.lang.reflect.*;

class B { 
  B() { System.out.println("B"); }
  void foo() { System.out.println("B.foo"); }
}

public class Test{
  B b;
  void bar() {
    b = new B() {
          class C { C() { System.out.println("inner C"); } }
          void foo() { System.out.println("inner foo"); }
    };
    b.foo();
}
public static void main(String[] args) throws Exception {
    Test test = new Test();
    test.bar();

    Class<?> enclosingClass = Class.forName("Test$1");
    Class<?> innerClass = Class.forName("Test$1$C");

    Constructor<?> ctor = innerClass.getDeclaredConstructor(enclosingClass);
    Object innerInstance = ctor.newInstance(test.b);
  }
}

This prints:

B
inner foo
inner C

So, yes, given the fact that we can use the mangled class name Test$1$C at runtime, and that reflection allows us to instantiate objects at runtime, too (see here for details), the final answer is: yes, it is possible.

But just for the record: that doesn't mean at all that one should ever do something like this in real code. This is a nice little puzzle to train creativity; but not suited for anything in the real world.

In the real world, an inner class within an anonymous inner class is a design bug. End of story.

Community
  • 1
  • 1
GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • So. there is no way to instantiate a class defined in Anonymous inner class?? – Suyash Jain Mar 23 '17 at 18:49
  • Funny anecdote along the way: I actually thought about "I never run into a JonSkeet answer when searching SO myself". And I just realize that the answer I got that "how to instantiate an inner class using reflection" ... from a JonSkeet answer. Very cool. Now I just two more updates to hit the daily limit, to end this kewl day ;-) – GhostCat Mar 23 '17 at 19:41
  • @GhostCat +1 deleted my answer since this solves the problem in a more direct and better way :) – Mikenno Mar 23 '17 at 19:59