Why can I anonymously subclass an enum but not a final class?

前端 未结 3 1578
说谎
说谎 2021-01-11 15:43

This code:

public class Sandbox {
    public enum E {
        VALUE {
            @Override
            public String toString() {
                return \"I         


        
相关标签:
3条回答
  • 2021-01-11 16:20

    If you take the following into account, your concern may be lessened:

    A class which has no non-private constructor is effectively final since it is impossible to declare its subclass outside of its body. It is a minor technical detail whether the class defined by an enum is declared final or not: it will in either case be effectively final.

    0 讨论(0)
  • 2021-01-11 16:39

    According to the JLS:

    An enum type is implicitly final unless it contains at least one enum constant that has a class body.

    In your example, VALUE has a class body and therefore E is not implicitly final.

    Edit: Here's a quick example that validates the claim:

    import java.lang.reflect.Modifier;
    
    public class Sandbox {
      public enum E {
        VALUE {};
      }
    
      public enum E2 {
        VALUE;
      }
    
      public static void main(String[] args) {
        System.out.println(E.class);
        System.out.println(E.VALUE.getClass());
        System.out.println("E.VALUE is subclass of E = " + E.VALUE.getClass().getSuperclass().equals(E.class));
        System.out.println("E modifiers: " + Modifier.toString(E.class.getModifiers()));
        System.out.println("E2 modifiers: " + Modifier.toString(E2.class.getModifiers()));
      }
    }
    

    You can see from the output that the compiler is adding the final modifier to E2 but not to E:

    class Sandbox$E
    class Sandbox$E$1
    E.VALUE is subclass of E = true
    E modifiers: public static
    E2 modifiers: public static final
    

    Edit #2: Even though E is not final and is subclassed by VALUE, explicitly trying to extend it such as with class Foo extends E or enum Bar extends E is a compile-time error according to 8.1.4. Superclasses and Subclasses:

    It is a compile-time error if the ClassType names the class Enum or any invocation of it.

    0 讨论(0)
  • 2021-01-11 16:46

    I think if you compare classes and enums, then the enum E can be compared to a class, and the enum value VALUE can be compared to an anonymous instance. Thus, your first example can be rewritten as following:

    public class Sandbox {
        public static class E {
            public static final E VALUE = new E() {
                @Override
                public String toString() {
                    return "I'm the value";
                }
            };
    
            @Override
            public String toString() {
               return "I'm the enum";
           }
        }
        public static void main(String[] args) {
            System.out.println(E.VALUE);
        }
    }
    

    0 讨论(0)
提交回复
热议问题