如何使用混合数据类型初始化泛型中的数组

时间:2019-08-31 14:46:22

标签: java arrays generics arraylist

我正在研究Java数组,此外,我正在研究泛型。下面是初始化数组的两种方法

int[] data = {1,2,3,4,5,6,7,8,9};

// or

int[] data;
data = new int[] {1,2,3,4,5,6,7,8,9};

但是当我使用泛型时,例如,我会混合使用数据类型,

String[] outcome = {"0 wins", "Tie" , "X wins"};

上面的数组具有String的单个数据类型。如果在数组中我有类似下面的内容怎么办

outcome = {7, "Tie" , 9.0};

现在我在数组中混合了数据类型。如何编写它,或者是否可以使用泛型?我可以用ArrayList做到吗?

谢谢

6 个答案:

答案 0 :(得分:2)

我想纠正这个问题:

  

但是当我使用泛型时,我会混合使用数据类型

泛型需要同类数据类型。例如,List<Integer>是只能容纳Integer的列表,而List<? extends Number>只能容纳Number的列表,其中涵盖了其他数字类型,例如{{ 1}},LongShort等...,但由类型Double引用。

无论如何,您正在寻找的是Bag-一个可以容纳任意对象的集合。您可以使用NumberObject[]来实现此功能,并且需要检查要使用的 each 元素的类型,因为在Java中无法拥有异构数据类型,这正是您要寻找的。

答案 1 :(得分:2)

tl; dr:我认为数组不适合解决该问题,您应该使用对象代替。


这不是您问题的直接答案,而是重新设计形式的答案。

首先,让我们解决您有关泛型和数组的声明。数组是协变且保留的,而泛型是不变且已擦除的。

  • 协变量表示,当B extends A时,您可以写A[] aArray = new B[someSize];不变表示不可能:ArrayList<A> aList = new ArrayList<B>();将导致编译时错误。
  • 保留表示在运行时保留有关类型的信息:数组始终“知道*其元素具有什么类型。已擦除表示该类型信息已消失编译后也称为Type Erasure

covaraint和保留vs.不变和已擦除的混合物很有可能使您陷入麻烦。这就是ArrayList uses an Object[] instead of a T[] as its backing datastructure的原因。


现在是实际问题。正如其他人已经说过的那样,我们可以继续前进并创建一个Object[]。我强烈建议您这样做,因为我们会丢失所有类型的信息。检索该信息的唯一方法是进行instanceof检查,这会使您的代码变得僵硬。假设您更改了条目的类型。在这种情况下,instanceof将返回false,可能导致不良行为,并且(最好的情况)某些测试会变成红色,或者(最坏的情况)我们可能不会注意到它。

现在如何解决这个问题?我们创建一个表示匹配结果的类:

public class MatchResult {
    private final int firstTeamScore;
    private final int secondTeamScore;

    public MatchResult(final int firstTeamScore, final int secondTeamScore) {
        this.firstTeamScore = firstTeamScore;
        this.secondTeamScore = secondTeamScore;
    }

    public int getFirstTeamScore() {
        return firstTeamScore;
    }

    public int getSecondTeamScore() {
        return secondTeamScore;
    }

    public String getResultForFirstTeam() {
        if (firstTeamScore > secondTeamScore) {
            return "Win"; // In an actual implementation, I would replace this with an enum
        } else if(firstTeamScore = secondTeamScore) {
            return "Tie";
        } else {
           return "Lose";
        }
    }
    // You can add a method public String getResultForSecondTeam(), I omitted it for brevity
}

我们赢了什么?我们有类型。分数总是int s,结果总是String s。例如,如果我们将getReultforFirstTeam()的类型从String更改为Enum,我们将在类型不再匹配的所有位置收到编译器错误。因此,我们磨练fail-fast design并被迫在必要时修改代码。因此,我们什至没有机会得到我们以前的偷偷摸摸的不受欢迎的行为。

答案 2 :(得分:1)

处理此问题的一种方法是创建一个Object数组,该数组可以容纳所有数据类型

Object[] outcome = {7, "Tie" , 9.0};

随后,您可以访问以下对象:

if(outcome[0] instanceof Integer){
   Integer i = (Integer) outcome[0];
}

反之亦然。

答案 3 :(得分:1)

outcome = {7, "Tie" , 9.0};

根本不合法。

在变量声明中,例如,只能使用这种语法-array initializer,在等号后省略元素类型-

Object[] outcome = {7, "Tie" , 9.0};

答案 4 :(得分:0)

如前所述,您可以使用Object数组。另外,您可以使用泛型类。这是一个示例:

public class Queue<E> {

    private ArrayList<E> queue;

    /**Unparametrized constructor**/
    public Queue() {
        queue = new ArrayList<E>();
    }

    /**Enqueues an element into the queue.**/
    public void enqueue(E val) {
        queue.add(val);
    }

    /**Dequeues an element from the queue.**/
    public E dequeue() {
        E output = queue.get(0);
        queue.remove(0);
        return output;
    }

    /**Gets the current size of the queue.**/
    public int size() {
        return queue.size();
    }
}

Read讨论泛型及其使用方法。

答案 5 :(得分:0)

由于Java .menuBlock { background-color: #35393b; height: 100vh; color: white; padding: 25px 0; width: 400px; transition: 1s; position: absolute; left: -400px; } #idishka:checked ~ .menuBlock { left: 0; } 中的所有对象,您将不得不创建对象数组:

extends Object

要查找索引x处的对象是否为Object[] arr = new Object[3]; //to add objects to it: arr[0]=new String("element at index 0"); arr[1]=new Integer(1); arr[2]=new Character('2'); ,则必须使用强制转换:

Integer

您也可以使用int x = (Integer)arr[x]; //x could be 0 or 1 or 2

ArrayList