I know this questions has been asked before, but mostly pretty specific regarding a certain library. And the answers given didn't really explain to me what was going on.
That's why I set up a pretty simple test scenario here, and tried to fiddle with it, but there are still some question marks! Online Java Example
The simple code consists of two files:
Main.java
public class Main
{
public static void main(String[] args) {
// this works, and inner1 and inner2 seem to be new instances
Outer.Inner inner1 = new Outer.Inner();
Outer.Inner inner2 = new Outer.Inner();
inner1.setName("Mario");
inner1.say();
inner2.setName("Luigi");
inner2.say();
// if Inner is not a public static class this gives this error:
// error: an enclosing instance that contains Outer.InnerNoStatic is required
Outer.InnerNoStatic inner3 = new Outer.InnerNoStatic();
}
}
Outer.java
public class Outer {
public static class Inner {
private String name;
public void say() {
System.out.println("Hi " + name);
}
public void setName(String name) {
this.name = name;
}
}
public class InnerNoStatic {
public void say() {
System.out.println("Hi from InnerNoStatic");
}
}
}
So it seems like even though the Inner
class is declared with static, we create two new instances called inner1 and inner2. Why is it called static then?
And in turn, if I remove the static, as in InnerNoStatic
how would I go about getting an instance of that class?
static
here dictates how Inner
and InnerNoStatic
are used with respect to Outer
.
Because Inner
is static in Outer
, it is not tied to any specific instance of Outer
(as always, a static member belongs to the class, not to any particular instance of that class). That explains how this compiles:
Outer.Inner inner1 = new Outer.Inner();
InnerNoStatic
, however, is an instance member (that's that: if it's not static, it is tied to a given member). And that explains why the compiler raises an error here:
Outer.InnerNoStatic inner3 = new Outer.InnerNoStatic();
Because InnerNoStatic
must be tied to an instance of Outer
, you need to use such an instance to create inner3
:
Outer.InnerNoStatic inner3 = new Outer().new InnerNoStatic(); //note the calls
Your can also use an existing instance.
Outer outer = new Outer();
Outer.InnerNoStatic inner3 = outer.new InnerNoStatic();
In both of these cases, an Outer
instance is used to build an InnerNoStatic
instance (there's just no variable pointing to the Outer
object created with new Outer().new InnerNoStatic()
)
Note: It's easy to confuse new Outer.Inner();
with new Outer().new Inner();
. These are not doing the same thing ("Outer" in the former is basically playing the role of a namespace, whereas new Outer()
in the latter is creating an Outer
object). That is, one constructor call (Inner()
) in the former, but two constructor calls in the latter (Outer()
and Inner()
).