Java 泛型并调用属于该类型的方法

Java 泛型并调用属于该类型的方法,java,generics,Java,Generics,我一直在尝试制作一个类来表示一副牌。然而,我想以一种可以是任何类型的卡的方式来创建它,它不需要知道它只需要能够存储、洗牌和一次一张地绘制它们,无论它们是uno卡、普通扑克牌还是交易卡。为此,我一直在尝试一些我听说过但没有使用过的东西——泛型 然而,我一直没有运气让它工作。绘制卡片时,它不会实例化、填充卡片或返回正确的类型。我尝试过混合和匹配,但我就是无法让它工作 以前有缺陷的代码被截断以节省空间,请查看以前的编辑。小结:我使用了Cardable而不是T,并且缺乏一般的泛型表达。 那么这将如何工作

我一直在尝试制作一个类来表示一副牌。然而,我想以一种可以是任何类型的卡的方式来创建它,它不需要知道它只需要能够存储、洗牌和一次一张地绘制它们,无论它们是uno卡、普通扑克牌还是交易卡。为此,我一直在尝试一些我听说过但没有使用过的东西——泛型

然而,我一直没有运气让它工作。绘制卡片时,它不会实例化、填充卡片或返回正确的类型。我尝试过混合和匹配,但我就是无法让它工作

以前有缺陷的代码被截断以节省空间,请查看以前的编辑。小结:我使用了Cardable而不是T,并且缺乏一般的泛型表达。

那么这将如何工作,我对泛型是完全陌生的。我一直在到处寻找,我一直听说类型擦除,类文本应该是一个参数,yadda yadda。。。但是ArrayList是如何做到的呢?为什么您只需键入
ArrayList()
,它就可以工作,而不需要像
ArrayList(String.GetClass())
这样可笑的东西

谢谢你抽出时间

编辑:Cardable是一个类,在该类中,可以放入牌组的任何卡都将扩展

Edit2:Perception的建议因此修正了我的代码,但我不确定如何调用来填充代码组。现在我可以接受一个数组,但最好是内部的,我不能完全确定我是否掌握了整个工厂的方法

公共类甲板
{
私人ArrayList cardsInDeck;
公共甲板()
{
cardsInDeck=newarraylist();
}
公共空白填充(T[]新卡)
{
cardsInDeck.clear();
对于(T卡:新卡)
{
添加(卡片);
}
洗牌();
}
公共提款卡()
{
T卡=空;
尝试
{
card=cardsInDeck.get(0);
}
catch(IndexOutOfBoundsException e)
{
System.out.println(“卡用完”);
e、 printStackTrace();
}
cardsInDeck。移除(0);
回程卡;
}
公开无效洗牌()
{
ArrayList newDeck=新ArrayList();
Random rand=新的Random();
而(!cardsInDeck.isEmpty())
{
int index=rand.nextInt(cardsInDeck.size());
newDeck.add(cardsInDeck.get(index));
cardsInDeck.移除(索引);
}
cardsInDeck=新甲板;
}
公共int getSize()
{
返回cardsInDeck.size();
}
}

问题是:
ArrayList
的实现不依赖于实际的类型E。这就是为什么不需要在构造函数中传递类型(如您所说,
new ArrayList(String.class)

如果您编写的泛型类由于某种原因必须确切知道泛型类型在运行时表示什么,那么您需要在构造函数中传递该类型,因为正如您所说,类型擦除将不允许您从
T
获取该类。您需要
需要知道其实际类型参数(String.class)的新MyClass

例如,假设一个类访问数据库并检索给定类的实例。类的实例存储在以该类命名的表中。例如:

class MyRepository<T> {
  T load(int id) { ... }
}

问题是:
ArrayList
的实现并不依赖于实际的类型E。这就是为什么不需要在构造函数中传递类型(如您所说,
newarraylist(String.class)

如果您编写的泛型类由于某种原因必须确切知道泛型类型在运行时表示什么,那么您需要在构造函数中传递该类型,因为正如您所说,类型擦除将不允许您从
T
获取该类。您需要
需要知道其实际类型参数(String.class)的新MyClass

例如,假设一个类访问数据库并检索给定类的实例。类的实例存储在以该类命名的表中。例如:

class MyRepository<T> {
  T load(int id) { ... }
}

您可以为此使用泛型,但该组将无法填充自身,因为它不知道要创建什么类的对象!根据您的描述,您需要的基本上是一个
ArrayList
,其中
T
可以是任何内容;它甚至不必是卡片。不过,您需要的是一种填充甲板的方法。为此,可以使用factory对象:

public interface CardGenerator<T> {
    T[] generateAllCards();
}

public class Deck<T> {
    private ArrayList<T> cardsInDeck;

    public Deck(CardGenerator<T> generator) {
        cardsInDeck = new ArrayList<T>();
        cardsInDeck.addAll(generator.generateAllCards());
    }
    . . .
}
公共接口卡生成器{
T[]生成循环记录();
}
公务舱甲板{
私人ArrayList cardsInDeck;
公共甲板(CardGenerator){
cardsInDeck=newarraylist();
cardsInDeck.addAll(generator.generateAllCards());
}
. . .
}

如果您愿意,您可以限制
T
的类型以扩展
Cardable
,但就
Deck
的逻辑而言(就您所描述的而言),这是不必要的。

您可以使用泛型来实现这一点,但Deck将无法填充自身,因为它不知道要创建什么类的对象!根据您的描述,您需要的基本上是一个
ArrayList
,其中
T
可以是任何内容;它甚至不必是卡片。不过,您需要的是一种填充甲板的方法。为此,可以使用factory对象:

public interface CardGenerator<T> {
    T[] generateAllCards();
}

public class Deck<T> {
    private ArrayList<T> cardsInDeck;

    public Deck(CardGenerator<T> generator) {
        cardsInDeck = new ArrayList<T>();
        cardsInDeck.addAll(generator.generateAllCards());
    }
    . . .
}
公共接口卡生成器{
T[]生成循环记录();
}
公务舱甲板{
私人ArrayList cardsInDeck;
公共甲板(CardGenerator){
cardsInDeck=newarraylist();
cardsInDeck.addAll(generator.generateAllCards());
}
. . .
}
如果愿意,您可以限制
T
的类型以扩展
Cardable
,但以
Deck
的逻辑为基础(如您所述)
public void populate(Cardable t)
    {
        cardsInDeck.clear();
        Cardable[] cardsMade;

        cardsMade = t.makeAllCards();

        for( Cardable card : cardsMade )
        {
            cardsInDeck.add( card );
        }


        shuffle();
    }