Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / May 2007

Tip: Looking for answers? Try searching our database.

values() of an Enumeration type that is a generic parameter?

Thread view: 
Eric Smith - 12 May 2007 07:53 GMT
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>>
  {
    public void doSomething ()
    {
      for (E index: E.values ())
        {
          // do stuff here
        }
    }
  }

The compiler says:

 Foo.java:55: cannot find symbol
 symbol  : method values()
 location: class java.lang.Enum<E>
     for (E index: E.values ())
                    ^
 1 error

Does E not inherit the values() method of the enumeration type?
Is there some other way I can do this?

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.

Any hints will be much appreciated!

Thanks!
Eric
Tom Hawtin - 12 May 2007 12:15 GMT
>   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
Lasse Reichstein Nielsen - 12 May 2007 14:44 GMT
> 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


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.