Benoît Dubreuil
Benoît Dubreuil

Reputation: 680

Java generics : wildcard extends class and include that class

Suppose you have this variable :

Class<? extends AssetKey<?>> assetKeyClass;

Then I can only set assetKeyClass to a subclass type of AssetKey. Is there a way to do that plus allowing the AssetKey class type itself?

Like this :

// Subclass
assetKeyClass = TextureKey.class;
// Class
assetKeyClass = AssetKey.class;

EDIT : Forgot to show some class code :

public class AssetKey<T> {
// ...
}

public class TextureKey extends AssetKey<Texture> {
// ...
}

Upvotes: 2

Views: 2153

Answers (3)

newacct
newacct

Reputation: 122489

An extends (or super) bound always includes the bound itself.

The problem in your case is that a class literal, like AssetKey.class, always has the type Class parameterized by the non-parameterized form of that class. So AssetKey.class has type Class<AssetKey>. And Class<AssetKey> is not a subtype of Class<? extends AssetKey<?>> because the raw type AssetKey is not a subtype of wildcard-parameterized type AssetKey<?>. (According to Java rules, the raw and parameterized versions of a type are not subtypes of each other.)

On the other hand, TextureKey.class has class Class<TextureKey>, which is a subtype of Class<? extends AssetKey<?>>, because the type TextureKey (a non-generic class) is declared to be a subtype of AssetKey<Texture>, which is a subtype of AssetKey<?>.

If you drop the wildcard, and just declare it as Class<? extends AssetKey> assetKeyClass;, it will work because AssetKey is a subtype of AssetKey, and thus Class<AssetKey> is a subtype of Class<? extends AssetKey>.

Upvotes: 3

Beno&#238;t Dubreuil
Beno&#238;t Dubreuil

Reputation: 680

As Johannes Kuhn commented, the answer is to remove the wild card so that it's :

Class<? extends AssetKey>.

Now I only need to know why it works.

Upvotes: 1

marekmuratow
marekmuratow

Reputation: 404

Usage with extends

Class<? extends AssetKey> assetKeyClass;

// Subclass
assetKeyClass = TextureKey.class;
// Class
assetKeyClass = AssetKey.class;

Usage with super

Class<? super TextureKey> assetKeyClass ;

// Subclass
assetKeyClass = TextureKey.class;
// Class
assetKeyClass = AssetKey.class;

Upvotes: 0

Related Questions