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?
Almost all reference types can be generic. This includes classes, interfaces, nested (static) classes, nested interfaces, inner (non-static) classes, and local classes. The following types cannot be generic: Anonymous inner classes .
1. Which of these types cannot be used to initiate a generic type? Explanation: None.
Which of these Exception handlers cannot be type parameterized? Explanation: we cannot Create, Catch, or Throw Objects of Parameterized Types as generic class cannot extend the Throwable class directly or indirectly.
Whenever you want to restrict the type parameter to subtypes of a particular class you can use the bounded type parameter. If you just specify a type (class) as bounded parameter, only sub types of that particular class are accepted by the current generic class. These are known as bounded-types in generics in Java.
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;
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With