views:

3538

answers:

6

Hi,

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

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.

Cheers, Don.

+26  A: 
Jon Skeet
very enlightening! thanks!
Chii
+1  A: 

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”.

Theine
+6  A: 

Here's the explanation I like best: Groking Enum (aka Enum<E extends Enum<E>>)

Alan Moore
+4  A: 

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 types that satisfy

 E extends Enum<E>


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

mauricen
A: 

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