179

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.

Cajunluke
  • 3,103
  • 28
  • 28
Dónal
  • 185,044
  • 174
  • 569
  • 824

8 Answers8

113

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.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I am really interested in the usefulness of this kind of thing versus the complexity. When I C#'ify your english description I get this:
        interface IBuilder
        {
            IMessage GetMessage();
        }
    
        interface IMessage
        {
            IBuilder GetBuilder();
        }
    
    
    – artsrc Mar 22 '12 at 02:12
  • 1
    @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 :) – Jon Skeet Mar 22 '12 at 06:45
  • @JonSkeet: I might be too late, but couldn't stop asking. Does the `>` really stops me to pass a type argument which is not the new type being defined? I mean, for example, I could define two subtypes - one is `public class First extends Enum`, and the other one is `public class Second extends Enum`. The declaration isn't stopping me to mix subtypes here. – MD Sayem Ahmed Jul 18 '13 at 09:49
  • 1
    @SayemAhmed: Yes, it doesn't prevent *that* aspect of mixing up the types. I'll add a note about this. – Jon Skeet Jul 18 '13 at 09:55
  • "The purpose is to give benefits in the right case rather than protect you from the wrong case." But in the case of `Enum` there are no benefits beyond the benefits that would be given by just `class Enum`. – newacct Feb 25 '15 at 05:17
  • 1
    "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. – newacct Feb 25 '15 at 05:18
  • @newacct: They have `compareTo` that *accepts* the type parameter though - and it enables other things like `EnumMap` to work. It's too early in the morning for me to think about this hard, but I'm pretty sure there *are* benefits to it... – Jon Skeet Feb 25 '15 at 06:51
  • 1
    @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>` would be sufficient. – newacct Feb 25 '15 at 09:53
  • @JonSkeet: And even if `Enum` could be manually subclassed, this whole `compareTo` thing can still be done with `class Enum` by making `compareTo` abstract, the language would provide a `compareTo` implementation for `enum` types, and if you manually subclass `Enum`, then you need to provide an appropriate `compareTo` that matches your type parameter. The fact that `compareTo` is non-abstract is a library design issue. – newacct Feb 25 '15 at 09:55
  • @newacct: I suspect that `class Enum>` would indeed be sufficient in most cases... but given that the enum classes *are* always autogenerated, why not express that extra information within the type system? I don't see it doing any harm, other than causing a bit of head-scratching... and I suspect that there *are* cases where it's useful, even if I'm still having a hard time coming up with an immediate example. Expressing more information in the type system usually feels better than expressing less... – Jon Skeet Feb 25 '15 at 10:01
  • 1
    @JonSkeet: Given that enum classes are always autogenerated, I am claiming that `class Enum` 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. – newacct Feb 26 '15 at 00:01
  • 1
    @JonSkeet: Also, if `Enum` subclasses weren't always autogenerated, the only reason you would need `class Enum>` over `class Enum` is the ability to access `ordinal` for `compareTo()`. However, if you think about it, it doesn't make sense from the language point of view to allow you to compare two different types of enums via their ordinals. Therefore, the implementation of `Enum.compareTo()` that uses `ordinal` only makes sense in the context of `Enum` subclasses being autogenerated. If you could manually subclass `Enum`, `compareTo` would probably have to be `abstract`. – newacct Feb 26 '15 at 00:06
  • @newacct: Maybe you're right. I'm not convinced yet, but maybe you're right. Either way, I don't really think it's appropriate to take this further in comments on an answer over 6 years old, so I'll bow out at this point. – Jon Skeet Feb 26 '15 at 06:44
  • Yes. I too noticed that what you mentioned in the Edit is still possible. In this case, `B.compareTo(A a)` will still compile, though it is semantically incorrect. – Rajan Prasad Dec 28 '17 at 12:22
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)

Maurice Naftalin
  • 10,354
  • 2
  • 24
  • 15
  • Sure I agree that `Season extends Enum`. But that doesn't explain why `Enum` has a bound on its type parameter, instead of just `class Enum` – newacct Nov 30 '13 at 08:07
  • @newacct Because there's nothing special about `Season`--the argument above applies to _any_ type that `Enum` can be parameterised on. So `Weekday` (or whatever) must extend `Enum`, etc, and in general any `E` must extend `Enum`. And that's exactly what the declaration says. – Maurice Naftalin Dec 12 '13 at 09:39
  • You still didn't get what I said. Just because the declaration is satisfied doesn't explain why it is necessary. – newacct Dec 12 '13 at 19:31
  • 1
    @newacct OK, I get it now: you'd like all enums to be instances of Enum, 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. – Maurice Naftalin Dec 15 '13 at 00:17
  • I don't understand what you mean by "to be instances of Enum". I would like `Season` to `extend Enum` and `Weekday` to `extend Enum`. It would still be 100% as type-safe as before. – newacct Dec 16 '13 at 09:16
  • 1
    @newacct Don't you want to insist that `Season` implements `Comparable`? – Maurice Naftalin Dec 17 '13 at 16:23
  • 1
    Well, if `Season` is created via an `enum` declaration, the compiler already makes it extend `Enum`. There is no point to "insist". If you define your own class that extends `Enum`, then it's already possible to make `Foo` extend `Enum`. – newacct Dec 17 '13 at 20:57
  • 2
    @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. – Maurice Naftalin Dec 19 '13 at 12:35
  • @MauriceNaftalin your last comment clarifies it for me. I suggest adding it to the answer. – Roland Apr 07 '14 at 16:20
  • 2
    @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. – newacct Feb 25 '15 at 06:09
  • 2
    @MauriceNaftalin: If Java didn't prohibit manually subclassing `Enum`, then it would be possible to have `class OneEnum extends Enum{}`, 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. – newacct Feb 25 '15 at 06:12
  • 2
    @MauriceNaftalin: If the ordinal was the reason, then `public class Enum>` would also suffice. – newacct Feb 25 '15 at 06:24
10

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!
    }
}
Andrey Chaschev
  • 16,160
  • 5
  • 51
  • 68
  • 2
    Your solution has an unchecked cast: `return (CHILD) this;` Consider adding a getThis() method: `protected CHILD getThis() { return this; }` See: http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#getthis – Roland Nov 28 '13 at 17:36
  • @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` is not the case), I'm ignoring them to save time. – Andrey Chaschev Nov 28 '13 at 22:46
  • 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 node = new Node() .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 Nov 29 '13 at 14:39
  • @Roland thanks, this is what I needed - will update the example when I'm free. – Andrey Chaschev Nov 29 '13 at 15:00
  • The following link is also good: http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#FAQ206 – Roland Nov 29 '13 at 15:57
  • This is wrong. `(SELF) this` is unsafe. `SELF` is a subtype of `Node` but `Node` (the type of `this`) is not a subtype of `SELF`. – newacct Nov 30 '13 at 08:02
  • Everything would work with `abstract class Node`. The `extends Node` doesn't really add anything. – newacct Dec 01 '13 at 04:59
  • @newacct `Node` will allow the subclass to return anything - and this is not intended, because the goal of returning `SELF` is to have chained method calls. Adding to this, your argument could be applied to the declaration of `Enum`, can't it? You might want to have a look at a real world example: http://grepcode.com/file/repo1.maven.org/maven2/org.jdbi/jdbi/2.49/org/skife/jdbi/v2/SQLStatement.java#SQLStatement. Btw, it uses unchecked casts, so though my initial version is not canonical, it could be practical. – Andrey Chaschev Dec 01 '13 at 08:47
  • @AndreyChaschev: "`Node` will allow the subclass to return anything, because the goal of returning SELF is to have chained method calls." So? If someone wants to make a class that returns something else, what's the problem? You can still use classes that return themselves and chain them just fine. Both cases are perfectly type safe, and Generics is for type safety. Plus, even with your declaration, it's possible to make a class that extends Node with a different type argument. For example, `class Foo extends Node`. – newacct Dec 01 '13 at 23:28
  • @AndreyChaschev: "Adding to this, your argument could be applied to the declaration of Enum, can't it?" I didn't claim it cannot be applied to the declaration of `Enum`. "look at a real world example:" So? Some random person uses something that is not necessary. What does that prove? – newacct Dec 01 '13 at 23:29
  • @newacct You would better claim this for `Enum` to make things clearer. This is an intent of the designers of the language. This adds a restriction to a type system, and you say, that it's would also be ok without such restriction. You're right and some languages even lack Generics. You could also say that it's ok to use a concise form of reflection on a regular basis, but it is just not a Java way. – Andrey Chaschev Dec 02 '13 at 06:48
  • @Andrey Good, you reinvented the wheel, in this case the [getThis](http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#getthis) method. Why not name it accordingly since your are just returning the `this` pointer? – Roland Dec 02 '13 at 07:44
  • @Roland I am not an author of the article, my initial version of the answer was lacking `getThis`. Formally, this is not type safe because it produces an unchecked cast. In my projects I don't use this, because it's verbose and I've never seen a cast error in this case so far. – Andrey Chaschev Dec 02 '13 at 08:01
  • @AndreyChaschev: Without Generics you would need casts because there's no type safety. This does not add any type safety, and in fact, doesn't even do what you claim it does. – newacct Dec 02 '13 at 10:09
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”.

kpirkkal
  • 274
  • 2
  • 6
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(){...}
}
nozebacle
  • 396
  • 1
  • 5
  • 16
  • It still allows me to create a `class Foo extends Node` where Foo is unrelated to City. – newacct Nov 23 '11 at 22:43
  • 1
    Sure, and is that wrong? I don't think so. The base contract provided by Node 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 Apr 24 '12 at 11:30
  • @mdma: I agree. So then what use does the bound provide, over just `class Node`? – newacct Nov 30 '13 at 08:09
  • 2
    @nozebacle: Your example does not demonstrate that "this particular structure is necessary". `class Node` is fully consistent with your example. – newacct Nov 30 '13 at 08:10
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.

Community
  • 1
  • 1
EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
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.

Hanzhou Tang
  • 351
  • 2
  • 6
-2

In the declaration class Enum<E extends Enum>, the type parameter E is used to define a generic type for the Enum class. Let's break and interpret this type parameter:

<E extends Enum>: This specifies that the type E must be a subclass of the Enum class, and the subclass itself is parameterized with the same type E. This means that E represents an enum type that extends the Enum class. Let's consider an example of how this type parameter could be used:

class MyEnum extends Enum<MyEnum> {
    public static final MyEnum VALUE1 = new MyEnum();
    public static final MyEnum VALUE2 = new MyEnum();

    // ... additional code for MyEnum
}

In this example, MyEnum extends the Enum class, fulfilling the type constraint E extends Enum. The type parameter E is replaced with MyEnum within the Enum class declaration, indicating that MyEnum is the specific enum type being defined.

Using this generic type parameter, the Enum class can enforce type safety and ensure that any specific enum type extends the Enum class.

Dónal
  • 185,044
  • 174
  • 569
  • 824
Raj
  • 1
  • 2
  • 1) This code is not valid as you can't extend `Enum`. 2) If you could extend `Enum`, then the constraint would not guarantee that the type parameter is the same type being defined, as `class SomeOtherEnum extends Enum` would also be valid. – newacct Jul 15 '23 at 04:16