2

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?

wschopohl
  • 1,567
  • 1
  • 11
  • 18

4 Answers4

1

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?

Objects of a "static" inner class are not tied to the objects of its enclosing class, opposite to non "static" inner classes. Having a "static" inner class instead of moving that class to the "top level" is a handy way of signalling to a user that objects of that inner class have not much use separate from the outer class, similar to e. g. Map.Entry.

And in turn, if I remove the static, as in InnerNoStatic how would I go about getting an instance of that class?

For example

public class Outer {

  private InnerNoStatic innerNoStatic = new InnerNoStatic();

  public InnerNoStatic getInnerNoStatic () {
    return innerNoStatic;
  }
  // ...

and

Outer.InnerNoStatic innerNoStatic = new Outer().getInnerNoStatic();
Smutje
  • 17,733
  • 4
  • 24
  • 41
1

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?

static implies more independence for the nested class. It's designed mainly to increase encapsulation, readability, maintainability and it's a nice way to logically group classes.

And in turn, if I remove the static, as in InnerNoStatic how would I go about getting an instance of that class?

The syntax is a bit different because you need an instance of Outer.

Outer.InnerNoStatic inner3 = new Outer(). new InnerNoStatic();
Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
1

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()).

ernest_k
  • 44,416
  • 5
  • 53
  • 99
1

Non-static inner classes always have a reference to a corresponding outer class. As a result, such class can be instantiated only by Outer class.

In opposite, a static inner class has no reference to Outer class and can be created by any other object, if visibility allows that. This is very similar to the behavior of static methods, that do not require an objects instance to be called.

kofemann
  • 4,217
  • 1
  • 34
  • 39