Daniel Pitts’ Tech Blog

Instantiating Java inner-class objects, from a different class.

Daniel, January 9th, 2007

It occurred to me one day, that if you’re inner class isn’t static, it needs to have a copy of the “this” reference of the outer class. Most of the time, inner classes are only instantiated from within the containing outer class, so it was apparent where the “outer.this” reference came from.

I started thinking of how one might instantiate the inner-class object from a completely separate class. I spent a little time experimenting, why bother reading the JLS, and found the right syntax.
I first tried “new outerObject.InnerClass()”, but that was a syntax error. My second try was the right one. “outerObject.new InnerClass()”. While it looks a little awkward (and I would never do it in production code), it is useful to know how it works. I wrote up an example program to demonstrate how it happens.

InnerClassTesting.java:

import java.util.ArrayList;
import java.util.Collection;

public class InnerClassTesting {
    public static void main(String[] args) {
        final MyOuterClass hello = new MyOuterClass("Hello");
        final MyOuterClass world = new MyOuterClass("World");
        final Collection<MyOuterClass.MyInnerClass> list = new ArrayListn<MyOuterClass.MyInnerClass>();
        list.add(hello.new MyInnerClass("MyFriend"));
        list.add(world.new MyInnerClass("WideWeb"));
        list.add(hello.new MyInnerClass("AndGoodbye"));
        list.add(world.new MyInnerClass("Time"));
        for (Object obj: list) {
            System.out.println(obj);
        }
    }
}

class MyOuterClass {
    private final String value;

    public class MyInnerClass {
        private final String value;

        public MyInnerClass(String value) {
            this.value = value;
        }

        public String toString() {
            return MyOuterClass.this.toString() + '.' + value;
        }
    }
    public MyOuterClass(String value) {
        this.value = value;
    }

    public String toString() {
        return value;
    }
}

Like I said, I wouldn’t do anything like this in production code. It definitely couples InnerClassTest with MyOutterClass’s implementation (rather than its interface). I think its interesting for the sake of knowing what a language can do, and I hope some of you have found some interest in it too.

Tags:

4 Responses to “Instantiating Java inner-class objects, from a different class.”

  1. Piotr Kobzda Says:

    Other, not obvious IMHO, but also interesting (and even more “esoteric” I think) feature of Java, is an ability of a single instance of inner class to have multiple (and different!) enclosing class’ instances.

    An example:

    class EnclosingInstancesTest {
      public static void main(String... _) {
         A a = new A();
         A.I ai = a.new I();
         assert(ai.outerA()==a);
    
         B b = new B();
         B.I bi1 = b.new I();
         assert(bi1.outerA()==b && bi1.outerB()==b);
         B.I bi2 = b.new I(a);
         assert(bi2.outerA()==a && bi2.outerB()==b);
      }
    }
    
    class A {
      class I {
        A outerA() { return A.this; }
      }
    }
    
    class B extends A {
      class I extends A.I {
        I() { }
        I(A a) { a.super(); }
        B outerB() { return B.this; }
      }
    }
    

    I don’t really know any important usage of that feature, but I hope it’s worth to know about it.

  2. Piotr Kobzda Says:

    Daniel, in my previous comment submission here, I used a <code> tag around my example, but it doesn’t looks so nice rendered on a page. So, my message needs some formatting (maybe also my English correction?) before publishing (of course, if you think it’s worth of that…). Possibly adding a <pre> tag around the code is enough… but I’m sure you can correct it the better way… :)
    Also, now I think that my example could be a bit nicer with all occurrences of “outer” replaced with “get” — of course, it works without that change as well. :-)

    TIA for correcting me! :-))

    BTW, it would be a nice feature of your web-site, to be able to correct/remove own postings before your acceptation.

    P.S. This message is not an article comment, and you can freely remove it.

    P.S.2 Nice site! :-)

  3. Daniel Says:

    I think you can edit comments if you’re logged in when you comment. Also, you can use <pre class=”code”> to denote code snippets on this site :-).

    Thanks for the comment.

  4. New Adventures in Software » More Stupid Java Tricks Says:

    […] but they don’t necessarily have to be instantiated within the scope of the parent class.  Daniel Pitts shows another way.  File this one under “ugly syntax” and “surely that’s not supposed to […]

Leave a Reply