T具有不兼容的Java泛型边界
我试图通过创建一个泛型的Card
和Deck
类来学习泛型,就像这样
卡片。java
package com.tn.deck;
public class Card<S extends Comparable<S>, R extends Comparable<R>> implements Comparable<Card<S, R>> {
private S suit;
private R rank;
public Card(S suit, R rank) {
this.suit = suit;
this.rank = rank;
}
@Override
public String toString() {
return "Card{" +
"suit=" + suit +
", rank=" + rank +
'}';
}
@Override
public int compareTo(Card<S, R> o) {
return rank.compareTo(o.rank);
}
}
甲板。java
package com.tn.deck;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public final class Deck<T extends Card> {
private List<T> deck;
public <S extends Comparable<S>, R extends Comparable<R>> Deck(int numberOfDecks, S[] suits, R[] ranks) {
this.deck = initializeDecks(numberOfDecks, suits, ranks);
shuffle();
}
private <S extends Comparable<S>, R extends Comparable<R>> List<T> initializeDecks(S[] suits, R[] ranks) {
return Arrays.stream(suits)
.flatMap(suit -> Arrays.stream(ranks).map(rank -> new Card<>(suit, rank)))
.collect(Collectors.toList()); // === It complains here. ===
}
private <S extends Comparable<S>, R extends Comparable<R>> List<T> initializeDecks(int numberOfDecks, S[] suits, R[] ranks) {
return IntStream.range(0, numberOfDecks)
.mapToObj(i -> initializeDecks(suits, ranks))
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
public void shuffle() {
Collections.shuffle(deck);
}
@Override
public String toString() {
return "Deck{" +
"deck=" + deck +
'}';
}
}
我得到的错误是
Error:(57, 25) java: incompatible types: inference variable T has incompatible bounds
equality constraints: T
lower bounds: com.tn.deck.Card<S,R>
可能只是我不懂泛型,但我真的很感激有人能向我解释我做错了什么
# 1 楼答案
在产生错误的方法中,您创建了一组
Card<S, R>
对象,然后试图将它们放入List
中。为了实现这一点,List
需要能够保存该类型的对象当且仅当对象的类是
T
或T
的子类时,List<T>
可以保存对象。所以,为了让这行工作,Card<S, R>
必须是T
的子类。现在,如果你看一下T
上的约束,你指定的是T
是Card
的一个子类。此约束不能保证将卡放入列表所需的关系,因此会出现错误# 2 楼答案
为什么会出现这种错误?泛型参数
T extends Card
是Card
的所有子类,包括它本身,在这里是允许的。当泛型参数T
是Card
的子类类型时,当代码initializeDecks
尝试返回超类实例而不强制转换时,就会发生错误。让我们看一个简单的具体例子:您可以按如下方式修复代码:
# 3 楼答案
这是因为您正在创建
Card
,但必须返回List<T>
。而且T
可以是Card
的任何亚型,而不是Card
本身当您使用泛型类并需要创建
T
(或任何已删除的泛型类型)的新实例时,您应该接受一个能够这样做的工厂。例如: