0

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).

4
  • 1
    Reading up on the subject of generics vs. wildcards, I believe it has something to do with the fact that the args passed to foo are defined in terms of Enum<?> and not Enum<T> Commented May 17, 2017 at 18:42
  • 1
    You're dealing with an enum type "?" And an enum type "T". They aren't the same, which is why you're getting the type based error Commented May 17, 2017 at 18:46
  • @Rocket6488: yes, this is the bad new, which one is the good one? Commented May 17, 2017 at 18:50
  • based upon the rules you have set forth, you have to change the definition for the one that can be changed into the one that can be changed Commented May 21, 2017 at 18:46

1 Answer 1

2

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 ) {
Sign up to request clarification or add additional context in comments.

3 Comments

"It's declaration cannot be changed"
Thanks for your answer. The problem of modify "bar" declaration is that I must also modify callers of "bar" and callers of the callers and so on. In general, replace always ".... ( ... Enum<?> ... )" to "... <T extends Enum<T>> ... ( ... T ...)". Do you think use "<T extends Enum<?>>" in foo (the option that compiles) can create any issue?
Yes it will create an issue. Type assertions require careful thought, not hurling darts at syntax options. Why are there layers upon layers of calls sharing the same argument type? This is an architecture​ flaw to repair, not work around. (Law of Demeter) The <T extends Enum<T>> answer is the correct answer. Don't throw it away in order to preserve a mistake.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.