简体   繁体   中英

Type mismatch with bounded wildcard ? super Type

I'm having a problem getting this type conversion working correctly. My guess is the bounded generic wildcard <? super SomeType> doesn't work with interface implementations.

// sample class definitions
public interface IFace<T> { ... } 
public class MyClass<T1, T2> { ... }
public class UtilityClass<T> {
    public List<MyClass<T, ? super IFace<T>>> getList() { ... }
}
public class Actor extends SomeObj implements IFace<TypeA> { ... }

// use...
UtilityClass<TypeA> utility = new UtilityClass<TypeA>();
List<MyClass<TypeA, Actor>> list = utility.getList();

Type mismatch: cannot convert from List<MyClass<TypeA, ? super IFace<TypeA>> to List<MyClass<TypeA, Actor>>

Citing Joshua Bloch's Effective Java 2nd Edition:

Do not use wildcard types as return types . Rather than providing additional flexibility for your users, it would force them to use wildcard types in client code.

Properly used, wildcard types are nearly invisible to users of a class. They cause methods to accept the parameters they should accept and reject those they should reject. If the user of a class has to think about wildcard types, there is probably something wrong with the class's API .

When you start working with generics, a real must-read is this tutorial . If you read the 'Generics and Subtyping` section on page 4 you will know why you get that error. It has nothing to do with the fact you are using an interface

Intuitively, one might try to resolve the issue by making the method generic:

public <X super IFace<T>> List<MyClass<T, X> getList() { ... }

But this syntax isn't allowed, as it typically doesn't make sense to give a lower bound to type parameters using super . See this article for a good explanation of why: http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeParameters.html#FAQ107

Edit:

Looking at your code, I think you may be confusing super with extends in specifying bounds of a type parameter. It would be meaningful if getList() returned a List<MyClass<T, ? extends IFace<T>>> List<MyClass<T, ? extends IFace<T>>> instead, as this is specifying an upper bound on the second type parameter of MyClass (in other words that type must be something implementing IFace<T> ).

As natix's answer points out , using wildcards in generic return types is discouraged because it effectively hides part the generic type information for the returned object. Instead, make the method generic:

public <X extends IFace<T>> List<MyClass<T, X> getList() { ... }

Which allows the calling code to specify the type of X through type inferrence.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM