Why Does Java Prohibit Static Fields in Inner Classes

Why does Java prohibit static fields in inner classes?

The idea behind inner classes is to operate in the context of the enclosing instance. Somehow, allowing static variables and methods contradicts this motivation?

8.1.2 Inner Classes and Enclosing Instances

An inner class is a nested class that is not explicitly or implicitly declared static. Inner classes may not declare static initializers (§8.7) or member interfaces. Inner classes may not declare static members, unless they are compile-time constant fields (§15.28).

Why are static methods allowed inside a non-static inner class in Java 16?

The specific reasoning is given in JEP 395

Static members of inner classes

It is currently specified to be a compile-time error if an inner class declares a member that is explicitly or implicitly static, unless the member is a constant variable. This means that, for example, an inner class cannot declare a record class member, since nested record classes are implicitly static.

We relax this restriction in order to allow an inner class to declare members that are either explicitly or implicitly static. In particular, this allows an inner class to declare a static member that is a record class.

In other words, it was necessary to remove the restriction on static members of inner classes for a particular case; i.e. to allow record classes to be declared in inner classes. But they decided to take the opportunity to remove the restriction in all cases.

This implies that the designers have concluded that the original restriction as a whole was neither necessary for technical reasons or desirable.



why did this restriction exist in the first place?

That is a more difficult question. The decision to make that restriction would have been made in 1996 or early 1997 when Java 1.1 was being designed. It is unlikely that anyone can still accurately remember the reasons behind original decision. So unless someone can find a contemporaneous written source, we will never know for sure.

(Brian Goetz commented above: "... at the time nested was added (Java 1.1), there were multiple possible interpretations of static within another class, so the question was deferred.". That certainly makes sense, but this could be (just) one person's recollection of something that happened ~25 years ago. If it was me, I wouldn't be confident in my memory from that far back. Unless I had contemporaneous minutes, notes, etc to refer to.)

There is some speculation about the rationale for the original restriction here:

  • Why does Java prohibit static fields in inner classes?

Why static fields (not final) is restricted in inner class in java

Your class myInnerClassTest isn't declared as static. So what would that exactly mean for it to have a static field ?

Would it be

  • the same for all instances whatever the enclosing instance ?
  • the same for all instances of this inner class having the same enclosing instance ?

At first sight most programmers would probably think it's the first case, while the encapsulation logic of the (non static) inner class should probably lead to the second choice. Either case (or both with different modifiers) would need a new definition of static which probably wasn't seen as necessary. And in either case programmers would be confused about the exact meaning.

From the specification :

An inner class is a nested class that is not explicitly or implicitly
declared static.

Inner classes include local (§14.3), anonymous (§15.9.5) and
non-static member classes (§8.5).

Inner classes may not declare static initializers (§8.7) or member
interfaces, or a compile-time error occurs.

Inner classes may not declare static members, unless they are constant
variables (§4.12.4), or a compile-time error occurs.

Why does java not initialise static nested class fields at the same time as static outter fields?

1) Is my understanding correct?

Basically yes. Consider what happens with your static member outerField :

public class OutterClass {

private static final OutterClass outterField = new OutterClass("outterField");

Theoretically, it's possible that the JVM could create that static final object when the program starts running, or when the class is loaded, but it doesn't. Instead, it'll only initialise it when needed - basically :

  • Instance of class is created, or
  • One of the Class's static fields or methods is accessed

(see https://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.1 )

So also with the static inner class. As you say, the JVM regards it as a top level inner class, so will only initialise its members when it also is needed.

2) Has this got anything to do with the JIT compiler or the class loader?

No and no. Initialisation of static members does not take place at class load time, but later (as we said, when the class is accessed). This is not a matter of compiler optimisation, but explicitly specified behaviour. After all, when you load a possibly-large class library, you would not want your JVM to consume memory or time initialising all the static members of classes that your program never touches; only-on-demand is a much better approach.

Is the InnerClass loaded when the OuterClass is loaded?

Yes (but not initialised then)

Why can't inner classes declare static members?

Basically just an arbitrary decision. there's no reason it couldn't be supported, but there is also not really any good reason to support it. just declare the static field in the outer class.

also, that quote may not be entirely correct: i believe you can declare a static serialVersionUID in an inner class.

Why can't I declare and initialize static variable in inner class?

You can't have static fields/method in a regular inner classes, because, inner classes will work only with instance of outer classes.

So, static can't be there with instances.

But they can have compile time constants, check JLS 8.1.3. You x, x1, x2 are not compile time constants, while s1, s2, y1, y2 are compile time constants

Inner classes may not declare static initializers (§8.7) or member
interfaces, or a compile-time error occurs.

Inner classes may not declare static members, unless they are constant variables (§4.12.4), or a compile-time error occurs.

Why do only static inner classes in Java have static members?

An inner class is a nested class that is not explicitly or implicitly
declared static. Inner classes may not declare static initializers
(§8.7) or member interfaces. Inner classes may not declare static
members, unless they are compile-time constant fields"

  • http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.1.3

Inner class belong to an instance of the out class, so it makes sense.



Related Topics



Leave a reply



Submit