tags:

views:

60

answers:

2

I've got some old command-line argument parsing code I wrote 4 years ago for Java 5, and it won't compile in Java 6 thanks to changes in how generics are handled and/or whether certain library classes are generic. While trying to fix it, I came across the following problem; since it's been 4 years since I've touched Java and I was never an expert at generics to start with, it's sort of stumping me.

The library allows me to specify that certain command-line options correspond to enums. To do this, the ArgumentSpecification object corresponding to this option wants to hold a Class object, which we'll call "enumClass", corresponding to the enum class. Unfortunately, I can't seem to figure out how to properly write the type of that field to constrain it to contain class objects that correspond to actual Enum classes. I think what I want is something like:

protected <E extends Enum<E>> Class<E> enumClass; // compiler error

but the compiler barfs on this. On the other hand, the compiler is completely happy with methods that have return values and/or parameters specified that way:

protected <E extends Enum<E>> Class<E> dummyTest(Class<E> foo) { return foo; } // "works"

I can try using this for the field instead:

protected Class<? extends Enum<?>> enumClass;

but that doesn't really work either...other parts of the code need the "<E extends Enum<E>>" type so they can actually get at E, and this doesn't seem to match up with the "<? extends Enum<?>>", as I get compiler errors like this:

Bound mismatch: The generic method checkedEnumFromString(Class<E>, String) of type EnumUtil is not applicable for the arguments 
 (Class<capture#1-of ? extends Enum<?>>, String). The inferred type capture#1-of ? extends Enum<?> is not a valid substitute for the bounded 
 parameter <E extends Enum<E>>

Is there a way to declare the field with the correct type here that I'm missing? If so, what is it? If not, isn't it horribly broken of Java to be able to declare types in methods that you can't for fields? Or am I so horribly confused that my question makes no sense to start with?

+2  A: 

If you need to define a field with explicit parameter E like that, then you may have to parameterize the type in which the field is declared in. Something like this compiles:

class MyClass<E extends Enum<E>> {
    Class<E> enumClass;
}
polygenelubricants
I was afraid of that...ugh. I think it'd actually be less kludgy in my case to just accept that Java's type system is retarded (thanks, type erasure!) and use "Class enumClass;" in conjunction with a liberal peppering @ShutTheHellUp("unchecked");Thanks for the response, though.
Scott Davies
+1  A: 

You're trying to declare a "generic field" - one which has a type parameter itself. There's no such concept in Java - only methods and types can introduce type parameters.

As polygenelubricants says, you can introduce an extra type parameter in the type itself, and use that as the type of the field.

Jon Skeet