Java Enum definition

Posted on 20th October 2015


At the dying ends of the work day, I came across this page and was initially confused by

public abstract class Enum<E extends Enum<E>>

Doesn't that look, well, horribly circular? Stackoverflow suggests this is common confusion.

Circularity is nothing to be afraid of: consider the type constraint <T extends Comparable<T>> which simply means (slightly loosely speaking) that T must implement compareTo(T o). You have to be able to compare to yourself.

So what does Enum<E extends Enum<E>> mean? Simply that we can only use Enum<E> for types E which extends Enum<E>, i.e. fulfil the contract guaranteed by Enum<E>. To my mind, this is slightly circular, as when checking the definition of Enum the compiler may need to decide if E can do something, for which it needs to know the definition Enum<E>.

The answer by Maurice Naftalin explains why we want this rather well. We want

public class MyEnum extends ...

where "..." is something to do with the generic Enum, and we want this to implement Comparable<MyEnum> automatically for us. What can we paramaterise Enum with? Well, we only have MyEnum so it better be (in fact, only can be) Enum<MyEnum>. Thus we need

MyEnum extends Enum<MyEnum>
Enum<MyEnum> implements Comparable<MyEnum>

Abstracting, we find that the constraint on E in Enum<E> is simply that E extends Enum<E>. That is, we arrive at the seemingly odd constraint completely naturally.

An Enum keeps an "ordinal", or what I'll call place below, to allow ordering. So, we want something like this:

public abstract class Thing<E extends Thing<E>>
    implements Comparable<E>
{
    private int place;
    public final int compareTo(E other) {
        return this.place - other.place;
    }
}

(Note that this is bad practice: I'm assuming place is small so over/underflows can't occur in the compareTo method). We know that E extends Thing<E> and so other fulfils the contract of Thing and hence has a field named place of type int. In this case, we could parameterise on <E extends Thing<?>> but for Enum we probably want the strong typing to ensure we don't compare two different Enum types.

More at Generics FAQ.

In C++, there is the related CRTP of which more to come...


Categories
Recent posts