[英]T has incompatible bounds - Java generics
我正在尝试通过制作一个看起来像这样的通用Card
and Deck
类来学习通用知识。
Card.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);
}
}
Deck.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>
可能只是我不了解泛型,但我真的很感谢有人向我解释我做错了什么。
发生这种情况是因为您正在创建Card
,但是必须返回List<T>
。 T
可以是Card
任何子类型,而不是Card
本身。
当您使用泛型类并需要创建T
的新实例(或任何已擦除的泛型类型)时,您应该接受能够这样做的工厂。 例如:
public <S extends Comparable<S>, R extends Comparable<R>> Deck(int numberOfDecks, S[] suits, R[] ranks, BiFunction<S, R, T> cardFactory) {
this.deck = initializeDecks(numberOfDecks, suits, ranks, cardFactory);
shuffle();
}
private <S extends Comparable<S>, R extends Comparable<R>> List<T> initializeDecks(S[] suits, R[] ranks, BiFunction<S, R, T> cardFactory) {
return Arrays.stream(suits)
.flatMap(suit -> Arrays.stream(ranks).map(rank -> cardFactory.apply(suit, rank)))
.collect(Collectors.toList());
}
private <S extends Comparable<S>, R extends Comparable<R>> List<T> initializeDecks(int numberOfDecks, S[] suits, R[] ranks, BiFunction<S, R, T> cardFactory) {
return IntStream.range(0, numberOfDecks)
.mapToObj(i -> initializeDecks(suits, ranks, cardFactory))
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
为什么会出现此错误? 泛型参数T extends Card
是所有的子类Card
,包括本身是允许在这里。 当泛型参数T
是Card
的子类类型时,则错误发生在您的代码initializeDecks
尝试返回超类实例而不进行强制转换的情况下。 让我们看一个简单的具体例子:
class Superclass{}
class Subclass extends Superclass{}
Subclass sub= ...;
// you can assign subclass's instance to superclass since it is-a superclass
Superclass sup = sub;
// you can assign superclass's instance to subclass you need casting it down
Subclass sub2 = (Superclass) sup;
您可以按以下方式修改代码:
<S extends Comparable<S>, R extends Comparable<R>>
List<? super T> initializeDecks(...){
....
}
在获取错误的方法中,您要创建一堆Card<S, R>
对象,然后尝试将它们放入List
。 为了使其正常工作, List
需要能够容纳该类型的对象。
甲List<T>
可以保持物体当且仅当对象的类是T
或的子类T
。 因此,要使此行正常工作, Card<S, R>
必须是T
的子类。 现在,如果您查看对T
的约束,则可以指定T
是Card
的子类。 此约束不能保证将卡片放入列表所需的关系,因此会出现错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.