简体   繁体   English

T具有不兼容的范围-Java泛型

[英]T has incompatible bounds - Java generics

I'm trying to learn generics through making a generic Card and Deck class which looks like this; 我正在尝试通过制作一个看起来像这样的通用Card and Deck类来学习通用知识。

Card.java 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 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 +
                '}';
    }
}

The error I get is 我得到的错误是

Error:(57, 25) java: incompatible types: inference variable T has incompatible bounds
    equality constraints: T
    lower bounds: com.tn.deck.Card<S,R>

It's probably just me not understanding generics, but I would really appreciate someone explaining to me what I'm doing wrong. 可能只是我不了解泛型,但我真的很感谢有人向我解释我做错了什么。

This happens because you're creating Card , but must return List<T> . 发生这种情况是因为您正在创建Card ,但是必须返回List<T> And T may be any subtype of Card , not Card itself. T可以是Card任何子类型,而不是Card本身。

When you're working with a generic class and need to create a new instance of T (or whatever erased generic type), you should accept a factory which is able to do so. 当您使用泛型类并需要创建T的新实例(或任何已擦除的泛型类型)时,您应该接受能够这样做的工厂。 For example: 例如:

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());
}

why this error occurs? 为什么会出现此错误? the generic parameter T extends Card is all of the subclass of Card including itself is allowed here. 泛型参数T extends Card是所有的子类Card ,包括本身是允许在这里。 when the generic parameter T is a subclass type of Card , then the error occurs where your code initializeDecks try to return a superclass instance without casting. 当泛型参数TCard的子类类型时,则错误发生在您的代码initializeDecks尝试返回超类实例而不进行强制转换的情况下。 let's see a simple concrete example: 让我们看一个简单的具体例子:

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;

you can fix your code as below: 您可以按以下方式修改代码:

<S extends Comparable<S>, R extends Comparable<R>> 
        List<? super T> initializeDecks(...){ 
  ....
}

In the method that's getting the error, you are creating a bunch of Card<S, R> objects and then trying to put them into a List . 在获取错误的方法中,您要创建一堆Card<S, R>对象,然后尝试将它们放入List In order for that to work, the List needs to be able to hold objects of that type. 为了使其正常工作, List需要能够容纳该类型的对象。

A List<T> can hold an object if and only if the object's class is T or a subclass of T . List<T>可以保持物体当且仅当对象的类是T或的子类T So, for this line to work, Card<S, R> has to be a subclass of T . 因此,要使此行正常工作, Card<S, R>必须是T的子类。 Now if you look at the constraints on T , what you specify is that T is a subclass of Card . 现在,如果您查看对T的约束,则可以指定TCard的子类。 This constraint does not guarantee the relationship that putting the cards in the list requires, so you get an error. 此约束不能保证将卡片放入列表所需的关系,因此会出现错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 边界不兼容错误:Java谓词泛型 - Incompatible bounds error: Java Predicate generics Java实体组件系统-推断变量T具有不兼容的范围 - Java Entity Component System - Inference variable T has incompatible bounds java:不兼容的类型:推理变量 T 具有不兼容的边界等式约束:下限:java.util.List&lt;&gt; 用于添加字段 - java: incompatible types: inference variable T has incompatible bounds equality constraints: lower bounds: java.util.List<> for adding field java:不兼容类型:推理变量T具有不兼容的边界等式约束:下限:java.util.List &lt;&gt; - java: incompatible types: inference variable T has incompatible bounds equality constraints: lower bounds: java.util.List<> 推断变量T具有不兼容的范围错误 - inference variable T has incompatible bounds Error 推断变量T具有不兼容的范围 - inference variable T has incompatible bounds java EnumSet,不兼容的类型:推断变量E具有不兼容的范围 - java EnumSet, incompatible types: inference variable E has incompatible bounds java:不兼容的类型:推断变量 RR 的边界不兼容 - java: incompatible types: inference variable RR has incompatible bounds 不兼容的类型:推理变量T具有不兼容的边界等式约束:捕获#1的? 扩展java.lang.Object - incompatible types: inference variable T has incompatible bounds equality constraints: capture#1 of ? extends java.lang.Object Java泛型的不兼容类 - Incompatible classes of java generics
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM