XoXo
XoXo

Reputation: 1599

What is the recommended/correct way to access fields in an inner class?

Suppose we have this class and its inner class:

/* Outer.java */
public class Outer {
    private static class Inner {
        private final Object foo;

        public Inner(Object foo) {
            this.foo = foo;
        }

        public Object getFoo() {
            return foo;
        }
    }

    Inner inner = parse(/* someMistery */);

    // Question: to access foo, which is recommended?
    Object bar = inner.getFoo();
    Object baz = inner.foo;
}

I am surprised that inner.foo works.

Since foo is private, it can be accessed only through getFoo(), right?

Upvotes: 9

Views: 3630

Answers (2)

Radiodef
Radiodef

Reputation: 37845

Since foo is private, it can be accessed only through getFoo(), right?

In this case, Outer has access to it too, because Inner is a member of Outer.

6.6.1 says:

[If] the member or constructor is declared private, [then] access is permitted if and only if it occurs within the body of the top level class that encloses the declaration of the member or constructor.

Note that it's specified to be accessible within the body of the top level class that encloses the declaration.

This means, for example:

class Outer {
    static class Foo {
        private Foo() {}
        private int i;
    }
    static class Bar {{
        // Bar has access to Foo's
        // private members too
        new Foo().i = 2;
    }}
}

Whether to use a getter or not is really a matter of taste. The important realization here is that outer classes have access to the private members of their nested classes.

As a recommendation, I would personally say:

  • If the nested class is private (only the outer class has access to it), I wouldn't bother even giving it a getter unless the getter does a computation. It's arbitrary, and somebody else can come along and choose not to use it. If the styles are mixed, the code has a vagueness. (Do inner.foo and inner.getFoo() really do the same thing? We have to go waste time examining the Inner class to find out.)
  • But you could go through a getter anyway if that's the style you are comfortable with.
  • If the nested class isn't private, use the getter so the style is uniform.

If you really want to hide the private members, even from the outer class, you can use a factory with a local or anonymous class:

interface Nested {
    Object getFoo();
}

static Nested newNested(Object foo) {
    // NestedImpl has method scope,
    // so the outer class can't refer to it by name
    // e.g. even to cast to it
    class NestedImpl implements Nested {
        Object foo;

        NestedImpl(Object foo) {
            this.foo = foo;
        }

        @Override
        public Object getFoo() {
            return foo;
        }
    }

    return new NestedImpl(foo);
}

As a pedantic note, your static class Inner {} is technically a static nested class, not an inner class. class Inner {} (without static) would be an inner class.

This is specifically defined to be so:

The static keyword may modify the declaration of a member type C within the body of a non-inner class or interface T. Its effect is to declare that C is not an inner class.

Upvotes: 11

salmanbw
salmanbw

Reputation: 1311

It all depends on your piece of code from where do you want to access that object. Since it is a static nested class, so you will be able to access your object from either ways. Refer to this link http://www.javatpoint.com/static-nested-class for better understanding of inner classes.

Upvotes: 0

Related Questions