13

How do I access a field of an outer class, given a reference to an object of the inner class?

class Outer
{
    int field;

    class Inner
    {
        void method(Inner parameter)
        {
            // working on the current instance is easy :)
            field = 0;
            Outer.this.field = 1;

            // working on another instance is hard :(
            parameter.field = 2;              // does not compile
            parameter.Outer.this.field = 3;   // does not compile
            parameter.outer().field = 4;      // This works...
        }

        // ...but I really don't want to have to write this method!
        Outer outer()
        {
            return Outer.this;
        }
    }
}

I also tried Outer.parameter.field and many other variants. Is there a syntax that does what I want?

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • isn't the purpose of an inner class to been used just inside its outer class? – Heisenbug Jun 30 '11 at 15:21
  • I think that is the way to do it. If you feel it's wrong maybe you can think refactoring or building those classes differently? – Luciano Jun 30 '11 at 15:22
  • 5
    I don't know of any other way to do that, but I will say that if you're having to do contortions like that, it usually means you should rethink the design. – Mike Deck Jun 30 '11 at 15:23
  • @Overbose - Lots of inner class instances are passed out to the world. Many Iterator classes, for instance, are inner classes of their Iterable collections. Inner classes help reduce namespace clutter (e.g., `Float`, `Arc2D.Float`, `CubicCurve2D.Float`, `DataBuffer.Float`, etc.) – Ted Hopp Jun 30 '11 at 15:36

3 Answers3

13

How about this solution:

class Outer
{
    int field;

    class Inner
    {
        final Outer outer = Outer.this;
        void method(Inner parameter)
        {
            // working on the current instance is easy :)
            field = 0;
            Outer.this.field = 1;

            // working on another instance:
            parameter.outer.field = 2; 
        }
    }
}
user1504714
  • 141
  • 1
  • 5
  • This is how I always do it, though I would have chosen a non-primitive field for your example. Storing only a reference to the parent scope and accessing fields through it avoids using a stale reference for `field` when that's an Object rather than a primitive, which is the key benefit of this approach. – KomodoDave Apr 16 '13 at 08:54
10

From outside the inner class, I believe that there's no way, given a reference to an inner class instance, to reference members of the outer class instance. From inside a non-static inner class, you can, of course, reference them using the Outer.this.* syntax.

Think of it this way: the inner class is actually a completely separate class. It has a compiler-generated field (usually named something weird like this$0). Within the inner class, the language allows you to reference that field using Outer.this; however, that syntactic sugar is not available outside the inner class itself. Neither is the compiler-generated field.

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
3

There are two ways to look at what you're doing, as a static method or as a non-static method.

At first glance, your example looks more like a static method, since it is manipulating the state of the parameter rather than its own state. The static problem has been covered before, e.g. see In Java, how do I access the outer class when I'm not in the inner class?

But your example is of a non-static method, and I think I see what you're getting and why you think that an outer reference should be possible. After all, there are other situations in which you can access implementation details of other instances of your own type -- for example, it's common to reference the input parameter's private member fields when overriding equals. Unfortunately I just don't think that java provides a way to refer to another's lexically enclosing instance. This probably has something to do with the way that java actually implements non-static inner classes. Java uses this$0 for its own purposes, but you do not have access to this synthetic field.

Community
  • 1
  • 1
jtoberon
  • 8,706
  • 1
  • 35
  • 48