3

As I know, Enum is abstract class, I write an Enum, then I do javap command, I got:

public abstract class com.tonyzhai.homework.TestEnum extends java.lang.Enum<com.tonyzhai.homework.TestEnum> {
  public static final com.tonyzhai.homework.TestEnum a;

  public static com.tonyzhai.homework.TestEnum[] values();
    Code:
       0: getstatic     #2                  // Field $VALUES:[Lcom/tonyzhai/homework/TestEnum;
       3: invokevirtual #3                  // Method "[Lcom/tonyzhai/homework/TestEnum;".clone:()Ljava/lang/Object;
       6: checkcast     #4                  // class "[Lcom/tonyzhai/homework/TestEnum;"
       9: areturn

  public static com.tonyzhai.homework.TestEnum valueOf(java.lang.String);

so, it cannot instantiation, my question is that abstract must be has no instance, so if use Enum implement Singleton pattern, how it create its own instance?

8
  • It would help if you'd show the Java source code... A simple enum doesn't end up generating an abstract class, as far as I'm aware. Commented Sep 24, 2015 at 18:56
  • 2
    Why are you looking at the java disassembler output? What is the source code? Commented Sep 24, 2015 at 18:57
  • Enum instances in Java are always instantiated when you declare them (that's when the constructor is called). Commented Sep 24, 2015 at 19:02
  • 1
    java.lang.Enum is indeed abstract, but that's irrelevant. Commented Sep 24, 2015 at 19:09
  • 1
    @dasblinkenlight: I believe the implementation of enum classes is abstract if and only if the individual enum constants override behavior from the top-level enum type. Commented Sep 24, 2015 at 19:21

2 Answers 2

3

Yes Enum is abstract but you cannot actually extend it, except for some special circumstances, see here for more information.

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

2 Comments

All enums implicitly extend java.lang.Enum.
Yes you're right, but that's a little bit different from actually making a class that extends Enum.
1

When you declare an enum, the compiler will fill in certain aspects to fulfill the contract. E.g. it will add a YourEnumType[] values() and a YourEnumType valueOf(String) method.

It will also make your constructor private, regardless of whether you declared it, and it will add implicit int and String parameters whose arguments get passed to the super constructor Enum(String, int). These match the name and ordinal and the compiler will also insert the appropriate arguments when the constants are created.

For example:

public enum Axis {
    HORIZONTAL(true), VERTICAL(false);

    private boolean isHorizontal;

    Axis(boolean horizontal) {
        isHorizontal=horizontal;
    }
    public Axis getOther() {
        return isHorizontal? VERTICAL: HORIZONTAL;
    }
    public static void main(String... arg) {
        for(Method m: Axis.class.getDeclaredMethods())
            System.out.println(m);
        System.out.println("constructor:");
        System.out.println(Axis.class.getDeclaredConstructors()[0]);
    }
}

will print

public static void Axis.main(java.lang.String[])
public static Axis[] Axis.values()
public static Axis Axis.valueOf(java.lang.String)
public Axis Axis.getOther()
constructor:
private Axis(java.lang.String,int,boolean)

So you see the compiler added methods as well as the constructor being private and having the additional parameters. Note, however, that it is up to the compiler, where and in which order it adds these two parameters. Since the constructor is private and only used within the class itself, there is no compatibility requirement about how the initialization exactly works.

Further, getting the Constructor reflectively doesn’t allow you to construct additional instances. The Reflection implementation recognizes that this is an enum and rejects such attempts. You would have to hack deeper into the implementation to make such things possible, but that’s counteracting the intention of enums anyway.

2 Comments

I add empty constructor in my Enum, then I do reflect and call newInstance() method, but it throws NoSuchMethodException, it said I have only enmu(String, int) constructor, but no my empty constructor
That’s the point. You will always have the two additional parameters, regardless of how you defined your constructor. But in principle, there is no standard regarding the resulting signature. In theory, there are other possibilities to implement it on binary level. You can’t invoke the constructor reflectively, anyway.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.