75

What I try to do is this:

public class History {
    public class State {
        public enum StateType {

Eclipse gives me this compile error on StateType: The member enum StateType must be defined inside a static member type.

The error disappears when I make the State class static. I could make State static, but I don't understand why I cannot declare an enum in an inner class.

Steven Roose
  • 2,731
  • 4
  • 29
  • 46
  • 1
    please take a look at this: http://stackoverflow.com/questions/700831/java-local-enums – nano_nano Feb 13 '13 at 16:23
  • 1
    Unless you wanted State to access methods in History, make State a [static class](http://stackoverflow.com/a/1353326/2054731). – ArneHugo Apr 15 '14 at 12:26

4 Answers4

101

This is allowed in Java 16+

This is no longer forbidden starting with Java 16 (and the later LTS release Java 17) thanks to JEP 395 relaxing the rules on some static types inside inner classes.

The new phrasing in §8.1.3. Inner Classes and Enclosing Instances is (emphsis mine):

All of the rules that apply to nested classes apply to inner classes. In particular, an inner class may declare and inherit static members (§8.2), and declare static initializers (§8.7), even though the inner class itself is not static.

This answer explains the change in more detail.

Before Java 16 it was forbidden:

enum types that are defined as nested types are always implicitly static (see JLS §8.9. Enums):

A nested enum type is implicitly static.

You can't have a static nested type inside a non-static one (a.k.a an "inner class", see JLS §8.1.3. Inner Classes and Enclosing Instances):

It is a compile-time error if an inner class declares a member that is explicitly or implicitly static, unless the member is a constant variable

Therefore you can't have an enum inner type inside a non-static nested type.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
  • Is there a certain reason that nested `enum` types are implicitly `static`? – mrbela Apr 21 '21 at 12:46
  • 1
    @mrbela: if non-static nested `enum` types were allowed, then what enclosing class instance should the enum values reference? That idea is incompatible with the basic tenents of an `enum` type (namely that there's a finite, well-defined set of instances). – Joachim Sauer Apr 21 '21 at 12:53
  • So what's the correct alternative? I want an `enum` that's associated with my inner class. – Daniel Chin Mar 16 '23 at 09:19
  • 1
    @DanielChin: I've just edited my answer to add the details that starting with Java 16 (more relevantly the Java 17 LTS release) this is actually allowed. So the alternative is to update to Java 17. If you can't, then you just have to put the enum "next to" the inner class (i.e. have it be a sibling rather than a child). – Joachim Sauer Mar 16 '23 at 09:44
19

If you declared an enum like this:

enum Suit {SPADES, HEARTS, CLUBS, DIAMONDS}

The Java compiler would synthetically generate the following class for you:

final class Suit extends java.lang.Enum<Suit> {
  public static final Suit SPADES;
  public static final Suit HEARTS;
  public static final Suit CLUBS;
  public static final Suit DIAMONDS;
  private static final Suit[] $VALUES;
  public static Suit[] values();
  public static Suit valueOf(java.lang.String);
  private Suit();
}

There is no intention to create other instances of this class other than those static fields already defined in it (as you could infer from its private constructor), but most importantly, and as mentioned in the accepted answer, a inner class cannot have static members (JLS §8.1.3. Inner Classes and Enclosing Instances), and since the enum synthetic class does, it makes it unacceptable as inner class.

Edwin Dalorzo
  • 76,803
  • 25
  • 144
  • 205
  • Shouldn't it be ```final static class Suit extends java.lang.Enum``` and not ```final class Suit extends java.lang.Enum``` because enum has static variables (```SPADES, CLUBS etc```) and an inner (nested non-static) class can't have static declarations? – Marko Cain Aug 01 '20 at 18:05
6

Already enough information from +Joachim Sauer, I am just adding some extra details.

You can define inner enum only if your inner class is static nested inner class. See below

private static class DbResource {

    public enum DB {
        MERGE_FROM, MERGE_TO, MAIN;
    }
}
Dhiral Pandya
  • 10,311
  • 4
  • 47
  • 47
2

This worked for my use-case:

public class History {

    public interface HConstants{
         public enum StateType { PAST,CURRENT,FUTURE}
    }

    //Inner class
    public class State implements HConstants{
        public StateType stateField = StateType.PAST;
K F
  • 1,368
  • 13
  • 20