tags:

views:

312

answers:

7

Hi all,

Surfing on the source code of Java, I found the following declaration:

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

How should it be interpreted? I'm stuck with it...

Thank you.

+1  A: 

You're not alone. Ken Arnold had this to say:

Or, to show the same point in brief, consider this: Enum is actually a generic class defined as Enum<T extends Enum<T>>. You figure it out. We gave up trying to explain it.

(from the blog entry Generics Considered Harmful)

Brian Agnew
Thank you for the link. I'm glad I'm not alone :)
ATorras
+1  A: 

Enum class requires a parameterized type, E, which is the subclass of Enum.

The type info, E, is needed for methods like compareTo(E o), which requires type info during class declaration (e.g. Comparable).

Java compiler automatically pass in type info when you create enum class, so you don't see it when you declare

enum MyType {...}

There are things that I don't like how generic is used. For example, why do we need to verbosely pass the class type to the interface when the interface only requires the class info? we can't have a default, or compiler is not smart enough nowadays?

e.g.

class String implements Comparable<String>
Oscar Chan
+1  A: 

E is the direct (usually concrete) subclass of Enum, used both with Comparable (Enum implements Comparable not Comparable) and a few other methods. It does this to access the actual subclass, which I suspect it needs for some of the internal implementation as well.

Kathy Van Stone
+1  A: 

This class is not an enumerator type. It is just a complex generic regular class. It is hard to tell (without see the whole code) why it is design like this. But I'll guess it may have anything to do with the concept of self type when you want to have a method returning the current type always.


public abstract class Enum<E extends Enum<E>> {
    E getMe() { return (E)this; }
}
public class E1 extends Enum<E1> {
    void doE2_only() {}
    void doE2() {
        // This line is to prove that Javac will see this.getMe() as a function of E1
        this.getMe().doE2_only();
    }
}
public class E2 extends Enum<E2> {
    void doE2_only() {}
    void doE2() {
        // This line is to prove that Javac will see this.getMe() as a function of E2
        this.getMe().doE2_only();
    }
}

Which again, has nothing to do with enumerator types.

Just a thougth;

NawaMan
Um. The "enum" keyword is implemented using a class Enum<> behind the scenes.
Jason S
After some investigation, it seems that it is a backend of enum type as you said.
NawaMan
Why the same construction with java.lang.Enum doesn't compile? Is javac blocking it? Why if so?
ATorras
Sorry, what do you mean by "Why the same construction wiht java.lang.Enum" does not compile?" You means you create a similar structure class and it does not compiled? I did try that (the code that I posted compiled and run). Would you elaborated?
NawaMan
+1  A: 

All the enum you create in your code will be created by a final class extending the Enum class.

public enum MyEnum { XYZ }

will become

public final class MyEnum extends Enum<MyEnum>

Or something like that (not sure if XYZ become an instance or a class extending it - also I think it is not really final, but rather the compiler will not let you extend an enum) ... Anyway, as such Enum is not really useful, because you cannot (should not) really "do" anything with it yourself.

It is still indirectly useful to read its javadoc/code to better understand what you can(not) do with you enum.

vdr
+3  A: 

The reason to use the bounded type > is probably explained by the PECS rule of thumb (explained in Effective Java by Joshua Bloch).

PECS stands for "Producer, extends; Consumer super", and it is an acronym that explains how and when to use bounded wildcards when designing generic methods.

Let's examine any abstract class with this signature.

public abstract class Foo <E extends Foo<E>> {

   public static void use(Foo<E> foo) {
      // use foo
   }
}

And another abstract class that doesn't use the bounded wildcard:

public abstract class Bar<E> {
   public static void use(Bar<E> bar)  {
      // use bar
   }
}

Our concrete classes are:

public class FooImpl extends Foo<FooImpl> {
  // ...
}
public class AnotherFooImpl extends Foo<AnotherFooImpl> { ... }

public class BarImpl extends Bar<BarImpl> {
   ///
}

public class AnotherBarImpl extends Bar<AnotherBarImpl> { ... }

Our main program is:

public class FooBar {
   public static void main(String[] args) {
      Foo.use(new FooImpl()); // works
      Foo.use(new AnotherFooImpl()); // works

      Bar.use(new BarImpl()); // doesn't work -- why?
      Bar.use(new AnotherBarImpl()); // doesn't work -- why?
   }
}

To make Bar.use(new BarImpl()) work, the wildcard must be used.

(I think - off the top of my head - I haven't compiled it, so I hope I'm right :)

Each enum element is really a subclass of the enum type:

enum Foo {
   FooImpl, AnotherFooImpl, ...;
}

There are some methods in the base Enum class that need to make sure they have an subclass of the correct type, and for that to work, that syntax is necessary.

I hope this helps (try the example if you have the time).

-- LES

LES2
Hi @LES2! Thank your for your answer but I was not able to compile Foo because it says that the "use" method can't "make a static reference to the non-static type E". The same happens with Bar class.
ATorras
public static <E extends<Foo<E>> void use(Foo<E> foo) { // use foo }You have to duplicate the generic type for the static method. Sorry.
LES2
+1  A: 

It's like quining! @LES2 is on the right track.

public abstract class Foo <E extends Foo<E>> 
{

   public static void use(Foo<E> foo) {
      // use foo
   }
}

If you have the following class:

public class FooImpl extends Foo<FooImpl> {
  // ...
}

then the magic that these recursive templates gives you, is that:

  • the Foo template requires that its parameter extends itself (Foo).
  • If the parameter class E, in turn, extends Foo<E> (it has to because of the previous point) then you have ensured that the Foo template has an "awareness" of its subclass, since its subclass is passed into it as a template parameter
  • which in turn means that Foo's methods can safely downcast the this pointer to its derived subclass E.
Jason S
OMG! My mind is quining trying to interpret it.
ATorras