182

I thought I understood Java generics pretty well, but then I came across the following in java.lang.Enum:

class Enum<E extends Enum<E>>

Could someone explain how to interpret this type parameter? Bonus points for providing other examples of where a similar type parameter could be used.

3

7 Answers 7

115

It means that the type argument for enum has to derive from an enum which itself has the same type argument. How can this happen? By making the type argument the new type itself. So if I've got an enum called StatusCode, it would be equivalent to:

public class StatusCode extends Enum<StatusCode>

Now if you check the constraints, we've got Enum<StatusCode> - so E=StatusCode. Let's check: does E extend Enum<StatusCode>? Yes! We're okay.

You may well be asking yourself what the point of this is :) Well, it means that the API for Enum can refer to itself - for instance, being able to say that Enum<E> implements Comparable<E>. The base class is able to do the comparisons (in the case of enums) but it can make sure that it only compares the right kind of enums with each other. (EDIT: Well, nearly - see the edit at the bottom.)

I've used something similar in my C# port of ProtocolBuffers. There are "messages" (immutable) and "builders" (mutable, used to build a message) - and they come as pairs of types. The interfaces involved are:

public interface IBuilder<TMessage, TBuilder>
  where TMessage : IMessage<TMessage, TBuilder> 
  where TBuilder : IBuilder<TMessage, TBuilder>

public interface IMessage<TMessage, TBuilder>
  where TMessage : IMessage<TMessage, TBuilder> 
  where TBuilder : IBuilder<TMessage, TBuilder>

This means that from a message you can get an appropriate builder (e.g. to take a copy of a message and change some bits) and from a builder you can get an appropriate message when you've finished building it. It's a good job users of the API don't need to actually care about this though - it's horrendously complicated, and took several iterations to get to where it is.

EDIT: Note that this doesn't stop you from creating odd types which use a type argument which itself is okay, but which isn't the same type. The purpose is to give benefits in the right case rather than protect you from the wrong case.

So if Enum weren't handled "specially" in Java anyway, you could (as noted in comments) create the following types:

public class First extends Enum<First> {}
public class Second extends Enum<First> {}

Second would implement Comparable<First> rather than Comparable<Second>... but First itself would be fine.

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

14 Comments

@artsrc: I can't remember offhand why it needs to be generic in both the builder and the message. I'm pretty sure I wouldn't have gone down that route if I hadn't needed it though :)
@SayemAhmed: Yes, it doesn't prevent that aspect of mixing up the types. I'll add a note about this.
"I've used something similar in my C# port of ProtocolBuffers." But that's different because builders have instance methods that return the type parameter type. Enum doesn't have any instance methods that return the type parameter type.
@JonSkeet: Well, 1) Enum cannot be manually subclassed, so it is already guaranteed that the parameter is the same as the type, even without the bound. 2) If Enum could be manually subclassed, the bound does not prevent the type parameter to be a different enum type than the instance's type. 3) If you are saying that compareTo just needs to use ordinal from any Enum, then a bound of class Enum<E extends Enum<?>> would be sufficient.
@JonSkeet: Given that enum classes are always autogenerated, I am claiming that class Enum<E> is sufficient in all cases. And in Generics you should only use a more restrictive bound if it's actually necessary to ensure type safety.
|
33

The following is a modified version of the explanation from the book Java Generics and Collections: We have an Enum declared

enum Season { WINTER, SPRING, SUMMER, FALL }

which will be expanded to a class

final class Season extends ...

where ... is to be the somehow-parameterised base class for Enums. Let's work out what that has to be. Well, one of the requirements for Season is that it should implement Comparable<Season>. So we're going to need

Season extends ... implements Comparable<Season>

What could you use for ... that would allow this to work? Given that it has to be a parameterisation of Enum, the only choice is Enum<Season>, so that you can have:

Season extends Enum<Season>
Enum<Season> implements Comparable<Season>

So Enum is parameterised on types like Season. Abstract from Season and you get that the parameter of Enum is any type that satisfies

 E extends Enum<E>

Maurice Naftalin (co-author, Java Generics and Collections)

12 Comments

@newacct OK, I get it now: you'd like all enums to be instances of Enum<E>, right? (Because if they are instances of an Enum subtype, the argument above applies.) But then you won't have type-safe enums any more, so losing the point of having enums at all.
@newacct Look at the definition of Enum. In order to compare one instance with another it has to compare their ordinals. So the argument of the compareTo method must have been declared as an Enum subtype, or the compiler will (correctly) say that it doesn't have an ordinal.
@MauriceNaftalin: Enum.compareTo() is declared as taking a parameter of type E. This is a standard library function and how it is implemented is not the user's concern. The Java language specifically prohibits users from manually subclassing Enum, and all compiler-generated enums have the type parameter be the same as the type itself anyway, so the standard library implementation can rely on this to perform an unsafe cast.
@MauriceNaftalin: If Java didn't prohibit manually subclassing Enum, then it would be possible to have class OneEnum extends Enum<AnotherEnum>{}, even with how Enum is declared right now. It would not make much sense to be able to compare one type of enum with another, so then Enum's compareTo wouldn't make sense as declared anyway. The bounds do not provide any help to this.
@MauriceNaftalin: If the ordinal was the reason, then public class Enum<E extends Enum<?>> would also suffice.
|
11

This can be illustrated by a simple example and a technique which can be used to implement chained method calls for sub-classes. In an example below setName returns a Node so chaining won't work for the City:

class Node {
    String name;

    Node setName(String name) {
        this.name = name;
        return this;
    }
}

class City extends Node {
    int square;

    City setSquare(int square) {
        this.square = square;
        return this;
    }
}

public static void main(String[] args) {
    City city = new City()
        .setName("LA")
        .setSquare(100);    // won't compile, setName() returns Node
}

So we could reference a sub-class in a generic declaration, so that the City now returns the correct type:

abstract class Node<SELF extends Node<SELF>>{
    String name;

    SELF setName(String name) {
        this.name = name;
        return self();
    }

    protected abstract SELF self();
}

class City extends Node<City> {
    int square;

    City setSquare(int square) {
        this.square = square;
        return self();
    }

    @Override
    protected City self() {
        return this;
    }

    public static void main(String[] args) {
       City city = new City()
            .setName("LA")
            .setSquare(100);                 // ok!
    }
}

14 Comments

Your solution has an unchecked cast: return (CHILD) this; Consider adding a getThis() method: protected CHILD getThis() { return this; } See: angelikalanger.com/GenericsFAQ/FAQSections/…
@Roland thanks for a link, I've borrowed an idea from it. Could you explain me or direct to an article explaining why is this a bad practice in this particular case? The method in the link requires more typing and this is the main argument why I am avoiding this. I've never seen cast errors in this case + I know that there are some inevitable cast errors - i.e. when one stores objects of multiple types to a same collection. So if unchecked casts are not critical and the design in somewhat complex (Node<T> is not the case), I'm ignoring them to save time.
Your edit isnt that different from before besides adding some syntactic sugar, consider that the following code will actually compile but throw a run time error: ` Node<City> node = new Node<City>() .setName("node") .setSquare(1);` If you look at java byte code you will see that due to type erasure the statement return (SELF) this; is compiled into return this;, so you could just leave it out.
@Roland thanks, this is what I needed - will update the example when I'm free.
The following link is also good: angelikalanger.com/GenericsFAQ/FAQSections/…
|
3

You are not the only one wondering what that means; see Chaotic Java blog.

“If a class extends this class, it should pass a parameter E. The parameter E’s bounds are for a class which extends this class with the same parameter E”.

Comments

1

This post has totally clarified to me these problem of 'recursive generic types'. I just wanted to add another case where this particular structure is necessary.

Suppose you have generic nodes in a generic graph:

public abstract class Node<T extends Node<T>>
{
    public void addNeighbor(T);

    public void addNeighbors(Collection<? extends T> nodes);

    public Collection<T> getNeighbor();
}

Then you can have graphs of specialized types:

public class City extends Node<City>
{
    public void addNeighbor(City){...}

    public void addNeighbors(Collection<? extends City> nodes){...}

    public Collection<City> getNeighbor(){...}
}

4 Comments

It still allows me to create a class Foo extends Node<City> where Foo is unrelated to City.
Sure, and is that wrong? I don't think so. The base contract provided by Node<City> is still honoured, only your Foo subclass less useful since you start working with Foos but get Cities out of the ADT. There may be a use case for this, but most likely simpler and more useful to just make the generic parameter the same as the subclass. But either way, the designer has that choice.
@mdma: I agree. So then what use does the bound provide, over just class Node<T>?
@nozebacle: Your example does not demonstrate that "this particular structure is necessary". class Node<T> is fully consistent with your example.
1

If you look at the Enum source code, it has the following:

public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, Serializable {

    public final int compareTo(E o) {
        Enum<?> other = (Enum<?>)o;
        Enum<E> self = this;
        if (self.getClass() != other.getClass() && // optimization
            self.getDeclaringClass() != other.getDeclaringClass())
            throw new ClassCastException();
        return self.ordinal - other.ordinal;
    }

    @SuppressWarnings("unchecked")
    public final Class<E> getDeclaringClass() {
        Class<?> clazz = getClass();
        Class<?> zuper = clazz.getSuperclass();
        return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper;
    }

    public static <T extends Enum<T>> T valueOf(Class<T> enumType,
                                                String name) {
        T result = enumType.enumConstantDirectory().get(name);
        if (result != null)
            return result;
        if (name == null)
            throw new NullPointerException("Name is null");
        throw new IllegalArgumentException(
            "No enum constant " + enumType.getCanonicalName() + "." + name);
    } 
}

First thing first, what does E extends Enum<E> mean? It means the type parameter is something that extends from Enum, and isn't parametrized with a raw type (it's parametrized by itself).

This is relevant if you have an enum

public enum MyEnum {
    THING1,
    THING2;
}

which, if I know correctly, is translated to

public final class MyEnum extends Enum<MyEnum> {
    public static final MyEnum THING1 = new MyEnum();
    public static final MyEnum THING2 = new MyEnum();
}

So this means that MyEnum receives the following methods:

public final int compareTo(MyEnum o) {
    Enum<?> other = (Enum<?>)o;
    Enum<MyEnum> self = this;
    if (self.getClass() != other.getClass() && // optimization
        self.getDeclaringClass() != other.getDeclaringClass())
        throw new ClassCastException();
    return self.ordinal - other.ordinal;
}

And even more importantly,

    @SuppressWarnings("unchecked")
    public final Class<MyEnum> getDeclaringClass() {
        Class<?> clazz = getClass();
        Class<?> zuper = clazz.getSuperclass();
        return (zuper == Enum.class) ? (Class<MyEnum>)clazz : (Class<MyEnum>)zuper;
    }

This makes getDeclaringClass() cast to the proper Class<T> object.

A way clearer example is the one that I answered on this question where you cannot avoid this construct if you want to specify a generic bound.

1 Comment

Nothing you've shown in compareTo or getDeclaringClass requires the extends Enum<E> bound.
0

According to wikipedia, this pattern is called Curiously recurring template pattern. Basically, by using the CRTP pattern, we can easily refer to subclass type without type casting, which means by using the pattern, we can imitate virtual function.

Comments

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.