Java中的泛型数组,强制所有类型都相同?

时间:2015-10-12 03:55:13

标签: java generics

只是在Java中使用泛型和东西,遇到了一个潜在的问题。这是我正在思考的简化版本

public class Test<T> {
    private T[] arrayOfGenerics;
    int top;

    public Test(int size) {
        arrayOfGenerics = (T[]) new Object[size];
        top = 0;
    }

    public void add(T toAdd) {
        arrayOfGenerics[top++] = toAdd;
    }

    public static void main(String[] args) {
        Test myTest = new Test(10);
        myTest.add("Some String");  //First value added is a String
        myTest.add(12);             //Way to make this NOT work, since myTest should only accept Strings now
    }

}

显然,这并没有多大用处,生产方面明智,但我想更复杂的数据结构,你想要具有泛型的灵活性,但仍然强制它们都必须是相同的类型。这是一种解释它的可怕方式,但回到上面的示例代码,是否有办法使它成为当有人实例化和Test的实例时,他们必须指定arrayOfGenerics的类型和是通过构造函数以某种方式坚持它,或者可能只是基于添加的第一种类型的值?

另一种解释它的方法,比如你正在实现自己的Stack或LinkedList数据结构。您希望它是所有相同类型的对象的堆栈。它可以是字符串,整数,等等,但它必须选择&#39;一个并坚持下去。

2 个答案:

答案 0 :(得分:4)

我认为你没有在这里有效地使用泛型。对于前者执行以下操作:

// With this statement, the types that can be contained in the
// instance is fixed now.
Test<String> myTest = new Test<>(10);
myTest.add("Some String"); // this will work
myTest.add(12);  // this won't compile

您确实声明Test具有泛型类型,但是,在原始代码中,您在构造实例时没有使用它。这实际上导致Test<Object>的实例。

在Java中,泛型被改装,并且由于他们不想破坏向后兼容性,他们必须允许构建“原始”实例。但是,编译器仍应提供有关“原始类型”的警告,并且可能IDE会要求您使用@SuppressWarnings("unchecked")明确表示您使用的是非参数化类型。

至于强制用户确保他们输入正确的类型,您可以做的最好的是运行时检查。也就是说,对于前者。构造函数可以将Class作为参数。在所有方法中,您确保给定的参数类型正确。但这并没有给你编译时检查。错误只能在运行时知道。

另一件事是,一旦确定使用泛型正确设计了API,您可能不必担心强制执行类型。如果API的用户不想使用特定类型,无论编译器发出警告,他们可能确实想要使用原始类型(或者,也许,他们不知道更好,他们还没有读过Effective Java)。即使是Java自己的API也不会在该领域做出任何额外的努力。对于前者以下代码有效,并且不会在运行时抛出任何异常:

List list = new ArrayList<String>();
list.add("xyz");
list.add(123);

答案 1 :(得分:0)

  

如果要创建全班,则必须为班级指定Generic类型为Test<String> myTest = new Test<>(10);   包含相同类型的对象。

然后您的课程无法添加其他类型的Objects。请参阅以下示例。

Test<String> myTest = new Test(10);
  1. myTest.add("Some String"); //works fine
  2. myTest.add(12); //not works
  3. 您已将数组的大小设置为Constructor。因此,您不能超过指定的大小。请执行以下修改以使大小随机。

    //constructor
    public Test() {
        top = 0;
        arrayOfGenerics = (T[]) new Object[top];
    }
    
    //add method
    public void add(T toAdd) {
        top++;
        T[] newArray = (T[]) new Object[top];
        newArray[top - 1] = toAdd;
        System.arraycopy(arrayOfGenerics, 0, newArray, 0, top - 1);
        arrayOfGenerics = newArray;
    }