> Foo.java:55: cannot find symbol
> symbol : method values()
[quoted text clipped - 4 lines]
>
> Does E not inherit the values() method of the enumeration type?
There is no values method in java.lang.Enum.
> Is there some other way I can do this?
Pass a Class<E extends Enum<E>> as enumType to your constructor.
Replace "E.values()" with enumType.getEnumConstants().
> I'm also rather unclear on why various JDK classes use
> <E extends Enum<E>> for their parameter; I can't quite seem to
> grasp what it means. I tried just using <E extends Enum>, but the
> compiler had the same complaint.
Enum has generic parameter, so that needs to be supplied.
Enum requires a generic parameter so that it can implement Comparable
correctly, and declare its getDeclaringClass method.
Tom Hawtin
> I'm trying to write a generic class using an enumeration as a type
> parameter, but I ran into trouble trying to iterate over the enumeration
> values:
>
> class Foo<E extends Enum<E>>
...
> for (E index: E.values ())
...
> The compiler says:
>
[quoted text clipped - 6 lines]
>
> Does E not inherit the values() method of the enumeration type?
No. First of all, static methods are never inherited.
Second, E here is a type variable with Enum as an upper bound,
so at best it can be used to access static methods on the Enum
class. Enum has no method called "values". The only static
method is "valueOf(Class<T>,String)".
> Is there some other way I can do this?
No. The code you have displayed have no chance of knowing the
type parameter "E" at runtime. You need to have access to an
actual value of that type, or the class object for it, in order
to use reflection.
> I'm also rather unclear on why various JDK classes use
> <E extends Enum<E>> for their parameter; I can't quite seem to
> grasp what it means. I tried just using <E extends Enum>, but the
> compiler had the same complaint.
That's because Enum itself is parameterized. It's a hack that attempts
to introduce self-types to Java classes.
It allows inherited methods to have the correct type for subtypes.
For Enum, the method signature for "compareTo(E)" is inherited, but
each concrete Enum type must specify their own type for "E" to be
comparable to each other. This is achieved by having, e.g.,
enum Foo { BAR, BAZ}
be implemented by a class of type "Foo extends Enum<Foo>". This way,
the subclass passes back its own type to the superclass signature
it inherits.
/L

Signature
Lasse Reichstein Nielsen - lrn@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'
Eric Smith - 12 May 2007 20:41 GMT
I wrote:
> I'm also rather unclear on why various JDK classes use
> <E extends Enum<E>> for their parameter; I can't quite seem to
> grasp what it means. I tried just using <E extends Enum>, but the
> compiler had the same complaint.
> That's because Enum itself is parameterized. It's a hack that attempts
> to introduce self-types to Java classes.
[quoted text clipped - 7 lines]
> the subclass passes back its own type to the superclass signature
> it inherits.
Thanks for the explanation. I don't think I understand it 100%, but
I'm closer.
I can understand parameterized types of the form <E1 extends SomeClass<E2>>.
It's just <E1 extends SomeClass<E1>> that seems quite confusing.
Eric
Eric Smith - 12 May 2007 20:52 GMT
> No. The code you have displayed have no chance of knowing the
> type parameter "E" at runtime. You need to have access to an
> actual value of that type, or the class object for it, in order
> to use reflection.
OK. So EnumMap is able to figure out the range of the Enum type
parameter only because the constructors get the class object
at runtime? And from the class object, it has to use reflection
to get the enumeration values?
Thanks,
Eric
Lasse Reichstein Nielsen - 13 May 2007 00:27 GMT
> OK. So EnumMap is able to figure out the range of the Enum type
> parameter only because the constructors get the class object
> at runtime?
Yes.
> And from the class object, it has to use reflection to get the
> enumeration values?
Actually, the Class<T> object has the method "T[] getEnumConstants()"
that returns the values of an enum type (or null, if the Class is not
an enum), so reflection isn't needed anyway. I hadn't noticed that
method before today :)
/L

Signature
Lasse Reichstein Nielsen - lrn@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'
Lew - 13 May 2007 17:28 GMT
> Actually, the Class<T> object has the method "T[] getEnumConstants()"
> that returns the values of an enum type (or null, if the Class is not
> an enum), so reflection isn't needed anyway.
That /is/ reflection.

Signature
Lew
ylandrin@gmail.com - 23 May 2007 14:37 GMT
> > Actually, the Class<T> object has the method "T[] getEnumConstants()"
> > that returns the values of an enum type (or null, if the Class is not
> > an enum), so reflection isn't needed anyway.
>
> That /is/ reflection.
Hummmm... not exactly. getEnumConstants() is only available (i.e.
returns something other than null)
when the class *is* an Enum class. Not really the behavior you expect
from reflection, that should be
independant from hypotheses on the nature of the class, and report
type-checking failures through
a few, well-defined runtime exceptions.
In my opinion, this is rather a hack to implement inheritance-aware
static fields,
in the particular case of <E extends Enum<E>> E
valueOf(Class<E>,String). Look at the implementation of Enum-related
methods in Class... you could do the same thing with a static
Map<Class<? extends Enum>,Enum[]>,
that would let you implement <E extends Enum<E>> E[] values(Class<E>),
but with much less performance.
And what object is Class-common, but updated/able whith inheritance?
The Class object, of course!
--
YLS