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

2

35

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();
    }

}
Ellswerth answered 25/7, 2021 at 18:2 Comment(6)
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.Oddfellow
A better question is: why did this restriction exist in the first place?Aholla
@BrianGoetz can you provide an answer to that? :)Phrase
@paulsm4 Anyhow we create an instance for the outer class right so thought it's meaning less. As Brian Goetz told I would like to know why did the restriction exist in the first place?Ellswerth
@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...Ulpian
@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.Aholla
P
29

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:

Paederast answered 26/7, 2021 at 3:18 Comment(3)
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.Wildebeest
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.Paederast
Yes, I'm just suggesting some reasons it might not have been allowed in older Java versions - adding to your last paragraph.Wildebeest
E
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.

Efren answered 25/7, 2021 at 18:16 Comment(1)
Yea ... that's because more people use Java than C# and more people could be impacted by any changes :-)Paederast
P
29

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:

Paederast answered 26/7, 2021 at 3:18 Comment(3)
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.Wildebeest
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.Paederast
Yes, I'm just suggesting some reasons it might not have been allowed in older Java versions - adding to your last paragraph.Wildebeest

© 2022 - 2024 — McMap. All rights reserved.