0

Right now I'm trying to figure out what exactly is a Enum in java. I know how they work and how/when to use them however I'm a little unclear on what exactly they are. Based on their behavior it seems to me they are nothing more than just a class with a private constructor. However it seems to me that the compiler is doing something special with them as Enums have a special method called values() which doesn't show up in the Enum class on the Oracle doc site.

My question is, what exactly are Enums and how does the compiler interpret them?

Albinoswordfish
  • 1,949
  • 7
  • 34
  • 50
  • 4
    Read http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html. After that, come back with a specific question. – Luiggi Mendoza Jul 10 '13 at 23:53
  • 1
    Did you even bother? [Javadocs](http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html) and [Wikipedia](http://en.wikipedia.org/wiki/Enumerated_type) are great places to start. Vote to close for lack of research. – jason Jul 10 '13 at 23:54
  • From the link above: *An enum type is a special data type that enables for a variable to be a set of predefined constants.* A usage for `enum`s: Singleton http://stackoverflow.com/q/70689/1065197 – Luiggi Mendoza Jul 10 '13 at 23:54
  • Yes I've read that document many times, I was curious as to if the compiler treats Enums differently than normal classes as 'values()' doesn't show up in java.lang.Enum but yet all inherited Enums have this method. – Albinoswordfish Jul 10 '13 at 23:58
  • @Albinoswordfish The compiler does "something special" with every kind of type, namely emit a classfile with the appropriate bytecode. For enums, this bytecode includes a bunch of methods specialised for the given type. The base `Enum` class isn't meant to show you all the methods and fields of every enum. (Obviously enough, since then you couldn't have the enum constants themselves in the class.) – millimoose Jul 11 '13 at 00:05
  • @Albinoswordfish Quoting the tutorial you've been linked to twice now: "The compiler automatically adds some special methods when it creates an enum. For example, they have a static values method that returns an array containing all of the values of the enum in the order they are declared." I recommend reading through it the many+1th time. – millimoose Jul 11 '13 at 00:06
  • 1
    It *is* in the docs. It is also in the [language specification](http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9): "In addition, if `E` is the name of an `enum` type, then that type has the following implicitly declared `static` methods: [...] `public static E[] values();` [...] Returns an array containing the constants of this enum type, in the order they're declared." – jason Jul 11 '13 at 00:07
  • Yes I'm aware of this that's why I brought up the values() as an example. I'm wondering what else or how else the compiler treats Enums differently if anything. Like it say's 'adds some special methods' what are these other methods. – Albinoswordfish Jul 11 '13 at 00:11
  • 1
    @Albinoswordfish: Read the [specification](http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9). It will tell you *everything*! Get use to reading the specification. You've wasted so much time already. – jason Jul 11 '13 at 00:12

1 Answers1

5

An enum is a class that inherits from the Enum class with (a) a private constructor, as you mentioned; and (b) a fixed, ordered list of named, final instances.

Under the covers, when you declare an enum:

public enum Foo {
    A(1) {
        public void bar() {
            System.out.println("A#bar");
        }
    },
    B(2) {
        public void bar() {
            System.out.println("B#bar");
        }
    },
    C(3) {
        public void bar() {
            System.out.println("C#bar");
        }
    };

    private Foo(int x) {
        // Code goes here...
    }

    public abstract void bar();
}

...you can imagine the compiler generates something like this:

public class Foo extends Enum<Foo> {
    public static final Foo A=new Foo(1) {
        public void bar() {
            System.out.println("A#bar");
        }
    };
    public static final Foo B=new Foo(2) {
        public void bar() {
            System.out.println("B#bar");
        }
    };
    public static final Foo C=new Foo(3) {
        public void bar() {
            System.out.println("C#bar");
        }
    };

    private Foo(int x) {
        // Code goes here...
    }
}

There are a couple other things that make enums special:

  1. The compiler knows that enums have a fixed list of instances. This allows it to do things like emit warnings if a switch doesn't have a case statement to handle each value.
  2. Each constant has a special, compiler-generated, 0-based, monotonically increasing, dense ordinal() value assigned to it. (In other words, the first has ordinal 0, then second has ordinal 1, and so on.) This allows for extremely efficient array-based data structures like EnumMap to be created.

I'm sure I'm missing a few things, but this is a good place to start.

sigpwned
  • 6,957
  • 5
  • 28
  • 48
  • A default visibility constructor is also allowed, although I consider this to be a "quirk" – Bohemian Jul 11 '13 at 00:01
  • @Bohemian Curious. Yes, I agree, that's a quirk. – sigpwned Jul 11 '13 at 00:06
  • I mean, good answer, don't want to subtract from it at all but the OP could also just read the [specification](http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9)! – jason Jul 11 '13 at 00:11
  • @Bohemian Possibly to enable laziness and let you type just `Foo() {...}` without specifying `private` explicitly. Since invoking enum constructors is disallowed anyway, its access level isn't that important, and its privacy would be implied. (Of course they could've also made it so omitting the access modifier is equivalent to `private` for enums, but that would be adding one more special case somewhere.) That is, subtle interactions with reflection and security notwithstanding, assuming enum constructors are callable with reflection which I'm not sure about right now. – millimoose Jul 11 '13 at 00:11