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?
To instantiate an inner class, you must first instantiate the outer class. Then, create the inner object within the outer object with this syntax: OuterClass. InnerClass innerObject = outerObject.
Rules of Local Inner Class:The scope of the local inner class is restricted to the block they are defined in. A local inner class cannot be instantiated from outside the block where it is created in. Till JDK 7, the Local inner class can access only the final local variable of the enclosing block.
It is also known as regular inner class. It can be declared with access modifiers like public, default, private, and protected. The syntax to declare member inner class in Java is like this: Syntax: class Outer { // A member inner class named Inner.
It can access any private instance variable of the outer class. Like any other instance variable, we can have access modifier private, protected, public, and default modifier. Like class, an interface can also be nested and can have access specifiers.
Since
foo
is private, it can be accessed only throughgetFoo()
, 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:
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.)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 typeC
within the body of a non-inner class or interfaceT
. Its effect is to declare thatC
is not an inner class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With