1. Introduction

When working with Java, enums serve as a convenient way to define a fixed set of constants. However, creating enums within inner classes can introduce some complexities and considerations in Java versions before Java 16.

In this tutorial, we’ll delve into historical constraints on static types within inner classes before Java 16 and then discuss the significant relaxation of these rules in Java 16 and later versions.

2. Historical Constraints on Static Types in Inner Classes

Before Java 16, the Java Language Specification (JLS) strictly enforced rules regarding static types within inner classes:

  • Nested enum types were implicitly static, as stated in JLS §8.9
  • It was prohibited to declare a static nested type (including enums) within a non-static nested type (inner class), as outlined in JLS §8.1.3

Let’s illustrate this constraint with an example in Java versions before Java 16:

public class Outer {

    public class Inner {
        public static enum MyEnum {
            VALUE1, VALUE2, VALUE3

    public static void main(String[] args) {
        Outer outer = new Outer();
        Outer.Inner.MyEnum value = Outer.Inner.MyEnum.VALUE1;

Attempting to define the MyEnum enum as a static member within the non-static inner class results in a compilation error in Java versions before Java 16.

3. Relaxation of Rules in Java 16 and Later Versions

Java 16 introduced a significant change with the implementation of JEP 395, which relaxed certain rules concerning static members within inner classes.

This relaxation was reflected in the updated phrasing of §8.1.3 in the JLS, explicitly allowing inner classes to declare and inherit static members, including static enums, despite the inner class itself not being static.

Accordingly, the previous code snippet will run successfully, and we can access enum constants (VALUE1, VALUE2, and VALUE3) using the fully qualified name Outer.Inner.MyEnum.VALUE1.

4. Conclusion

In conclusion, the relaxation of rules in Java 16 and later versions regarding static types within inner classes, including enums, represents a significant evolution in Java’s language features. Moreover, this change enables developers to adopt more flexible and expressive coding patterns, enhancing the encapsulation and organization of code within inner classes.

As always, we can find the complete code samples for this article over on GitHub.