38

We know that a non-static inner class can be accessed using the instance of the outer class, so a static method is less meaningful inside a non-static class. But from Java 16 static methods are allowed inside a non-static inner class.

Why did this restriction exist in the first place? Why is this allowed in the newer version?

public class OuterClass { class InnerClass { static void printMe() { System.out.println("Inside inner class"); } } public static void main(String[] args) { InnerClass.printMe(); } } 
7
  • 15
    re Why it is allowed in the newer version? Probably because it's useful. I've occasionally wished for this. A method encapsulated in its rightful place that nevertheless does not depend on any instance, inner or outer, seems well-defined. Commented Jul 25, 2021 at 18:04
  • 39
    A better question is: why did this restriction exist in the first place? Commented Jul 25, 2021 at 20:48
  • 5
    @BrianGoetz can you provide an answer to that? :) Commented Jul 25, 2021 at 23:03
  • 3
    @AndyTurner My impression was that they wanted to pretend that each instance of the outer class had a whole new inner class, as if outer1.InnerClass was a different class from outer2.InnerClass. Of course, that's not how it actually works, but by prohibiting static they could keep the illusion up a bit longer... Commented Jul 26, 2021 at 14:59
  • 10
    @AndyTurner The answer from user253751 is mostly correct -- at the time nested was added (Java 1.1), there were multiple possible interpretations of static within another class, so the question was deferred. Commented Jul 26, 2021 at 15:57

2 Answers 2

39

You're asking for reasoning of a change in Java 16, so you should start by checking the Release Notes to see if it has anything to say. It does:

JEP 395: Records (JDK-8246771)
tools/javac
Records have been added to the Java language. Records are a new kind of class in the Java language. They act as transparent carriers for immutable data with less ceremony than normal classes.

Since nested classes were first introduced to Java, with the exception of static final fields initialized by constant expressions, nested class declarations that are inner have been prohibited from declaring static members. This restriction applies to non-static member classes, local classes, and anonymous classes.

JEP 384: Records (Second Preview) added support for local interfaces, enum classes, and record classes, all of which are static definitions. This was a well-received enhancement, permitting coding styles that reduce the scope of certain declarations to local contexts.

While JEP 384 allowed for static local classes and interfaces, it did not relax the restriction on static member classes and interfaces of inner classes. An inner class could declare a static interface inside one of its method bodies, but not as a class member.

As a natural next step, JEP 395 further relaxes nesting restrictions, and permits static classes, methods, fields, etc., to be declared within inner classes.

For further details, see JEP 395.

Sign up to request clarification or add additional context in comments.

1 Comment

Yea ... that's because more people use Java than C# and more people could be impacted by any changes :-)
33

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:

4 Comments

Some good motivations for disallowing static mutable state (i.e. no static fields except constants) in classes declared in non-static contexts would be (1) they aren't needed, since they'd be equivalent to fields of the outer instance, (2) many programmers would expect them to be equivalent to static fields of the outer class, i.e. global, leading to confusion, (3) static initializers (and static fields with initializer expressions) would need to executed after (and for each) instance creation, instead of just once when the class is loaded, complicating the class loader.
That is by the by. The point is that current group of people who are responsible for the Java language clearly were not persuaded by such reasons.
Yes, I'm just suggesting some reasons it might not have been allowed in older Java versions - adding to your last paragraph.
OK ... I understand what you are saying. But those or just possible reasons why they might have put the restriction in. We don't know the actual reasons. Brian Goetz's comment is probably the closest we will get.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.