将T [](其中T是Byte [])返回到Byte []

时间:2012-04-26 09:11:30

标签: java arrays generics java-6

我有一个Java JUnit 4测试和一个创建通用数组的泛型类。当我创建一个返回此通用数组的方法时,我会在返回它时收到错误消息。如果我将ArrayList(其中T是通过类实例化的Byte)返回到ArrayList,它就可以工作。

为什么数组似乎是实例化的和可用的(在更复杂的类上测试)但我不能返回对该数组的引用?

错误:

java.lang.ClassCastException: [Lcom.waikato.assignment.Object; cannot be cast to [Ljava.lang.Byte;
at com.waikato.testing.TestJava.test(TestJava.java:20)

类别:

public class TestClass<T> {
    T[] array;

    @SuppressWarnings("unchecked")
    public TestClass() {
        array = (T[]) new Object[32];
    }

    public T[] getArray() {
        return array;
    }

    public boolean doThing() {
        T[] t = array;

        return t == array && t != null;
    }
}

测试

public class TestJava {

    @Test
    public void test() {
        TestClass<Byte> t = new TestClass<Byte>();
        Byte[] b = t.getArray(); // Crash caused

        assertTrue(t.doThing()); // Works when above line is removed.
        assertTrue(b.length != 0);
    }

}

4 个答案:

答案 0 :(得分:5)

可以通过反射构建“通用”数组:

T[] array = (T[]) Array.newInstance(Byte.class, 32)

Byte.class替换为对所需类的引用。换句话说:

public class TestClass<T> {
    T[] array;

    @SuppressWarnings("unchecked")
    public TestClass(Class<T> type) {
        array = (T[]) Array.newInstance(type, 32);
    }

    public T[] getArray() {
        return array;
    }

    public boolean doThing() {
        T[] t = array;

        return t == array && t != null;
    }
}

您可以这样验证:

public static void main(String[] args) {
    TestClass<Byte> test = new TestClass<Byte>(Byte.class);
    // No ClassCastException here
    Byte[] array = test.getArray();
    System.out.println(Arrays.asList(array));
}

由于类型擦除,如果不使用Class<?>对象作为构造函数参数,则无法解决此问题。

答案 1 :(得分:2)

array = (T[]) new TestClass[32];

对我来说这看起来不像Byte[],编译器应该警告你在运行时忽略了通用转换。

这是通用解决方案

TestClass(Class<T> tclass){
   //create an array for the generic type
   array = (T[])java.lang.reflect.Array.newInstance(tclass,32);
}


TestClass<Byte> bTest = new TestClass(Byte.class);

答案 2 :(得分:1)

有一种方法可以找出通用类型类的实际类型参数。

我刚刚为Main类更改了这样的构造函数。

public class TestClass<T> {
T[] array;

@SuppressWarnings("unchecked")
public TestClass() {
    Class<T> objClass;
    objClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; // Found the type paramenter
    array = (T[]) Array.newInstance( objClass, 32);
}

public T[] getArray() {
    return array;
}

public boolean doThing() {
    T[] t = array;

    return t == array && t != null;
} }

和测试方法..

@Test
public void test() {
    TestClass<Byte> t = new TestClass<Byte>(){}; // Added {}
    Byte[] b = t.getArray(); 

    Assert.assertTrue(t.doThing()); 
    Assert.assertTrue(b.length != 0);
}

答案 3 :(得分:0)

这一行错了:

public TestClass() {
    array = (T[]) new TestClass[32];
}

这与你的问题的标题相矛盾,即“T是Byte”,因为T被初始化为TestClass。

一个想法是将数组更改为List&lt; T&gt;。