pasaba por aqui
pasaba por aqui

Reputation: 3519

java generic method with enum parameter type

With the following method definition:

protected <T extends Enum<T>> Tuple4< Boolean, String, T, String> foo( T... args ) {
...
}

(that is, a method that accepts any kind of Enum as argument, uses it internally and returns an instance of this class)

and using it as:

    protected String bar( Enum<?>... args ) {
...
        foo( args );
...

compiler complains:

error: method foo in class xxxx cannot be applied to given types;

However, if I change "foo" declaration, using Enum instead of Enum as in:

protected <T extends Enum<?>> Tuple4< Boolean, String, T, String> foo( T... args ) {
...
}

everything compiles ok.

I do not understand the origin of the first error and which is the best way to write this code.

Which difference there are in use at "foo" the term "<T extends Enum<T>>" (something recursive that always cause me some doubts) or use "<T extends Enum<?>>" ?

(note: assume "bar" implementation can be changed but its declaration can not be changed).

Upvotes: 0

Views: 1679

Answers (1)

dumptruckman
dumptruckman

Reputation: 114

The ? in Enum<?> is a wildcard. You can think of this as an unknown enum. All we know about it is that it is some type of enum but we can't ever be sure what type.

On the other hand, Enum<T> is a generic enum. We know it's an enum and we also know it is specifically type T.

There are some important differences between the generic enum and the unknown enum. For example, since we don't know what type the unknown enum is we can't use the method add(someEnumVal) on a List<Enum<?>>. This is because we can never be sure what type of enums are in the list. However, you can call add(someEnumVal) on a List<Enum<T>> (assuming someEnumVal is of type T) because we can be sure that the list is for enums of type T.

As for the better option? Personally, I would prefer to use the generic over a wildcard. However, this would mean you have to be able to modify your bar method to something like:

protected <T extends Enum<T>> String bar( T... args ) {

Upvotes: 2

Related Questions