通用阵列非常规铸造

时间:2014-02-16 06:17:29

标签: java arrays generics

我正在构建一个通用的HashTable类,我们使用简单的Java .hashCode()方法将一个键转换为hash,以数组大小为模,并存储在结果的索引中。唯一的问题是,教授希望我们不仅存储价值,还存储我们散列的关键。为此,我创建了一个Data类,用于存储和获取两个值:

private class Data {
    private K key;
    private V value;

    public Data(K key, V value) {
        this.key = key;
        this.value = value;
    }

    public K getKey() {
        return key;
    }

    public V getValue() {
        return value;
    }
}

非常简单的东西。当我尝试创建数据项数组以保存散列值和创建它们的键时,会遇到困难。 K和V是HashTable类声明中指定的通用值:

public class HashTable<K,V> implements Table<K,V>

当我第一次创建类时,我只是在对象数组上使用强制转换来创建V的数组,但由于我们需要存储这两个值,所以我决定创建Data类并存储它们。但是当我用我的

尝试时
hashArray = (Data[])new Object[arraySize];

它给了我错误

Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Lproject3.HashTable$Data;

这使我无法创建数据类型的数组。是否有另一种方法可以在不使用List的情况下存储它(因为这是分配的参数)?

1 个答案:

答案 0 :(得分:4)

Object[]不是Data[]。该转换在运行时必然会失败。但由于那里已经知道了这种类型,为什么不直接创建Data[]?没有必要创建Object[]并尝试投射它。

现在回答你的另一个问题,下面的演员:

V[] arr = (V[]) new Object[arraySize];

有效,因为V的类型在运行时是未知的。类型信息被删除。并且因为类型参数的擦除是最左边的边界,在这种情况下是Object,所以在运行时上面的转换如下所示:

Object[] arr = (Object[]) new Object[arraySize];
好像很好,不是吗?但是,只要让数组转义类,这种方式也会失败,并将返回值分配给任何引用,如下所示:

HashTable<String, Integer> map = new HashTable<String, Integer>();
// suppose you have a getter to get the array stored
Integer[] arr = map.getValueArray();

上面第二行将在运行时抛出ClassCastException,原因与上面发布的相同。因此,将Object[]转换为V[]将起作用,直到您不让数组逃脱该类。

现在,考虑另一种情况,你给V绑定,说V extends Comparable<V>,看看会发生什么;

public class MyClass<T extends Comparable<T>> {
    T[] arr;

    public MyClass() {
        arr = (T[])new Object[0];
    }
}

在这种情况下,类型参数T的擦除为Comparable,因此构造函数中的强制转换将被删除为:

arr = (Comparable[]) new Object[0];

这将再次抛出ClassCastException,无论你是否让数组逃脱了类。

所以,重点是,在创建泛型类型数组时需要非常小心。


另见