3

Java JUnit 4テストと、ジェネリック配列を作成するジェネリッククラスがあります。このジェネリック配列を返すメソッドを作成すると、返すときにエラーメッセージが表示されます。ArrayList(Tはクラスのインスタンス化によるバイト)を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

4 に答える 4

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<?>型消去のため、オブジェクトをコンストラクター引数として使用しないと、この問題を解決できません。

于 2012-04-26T09:18:19.200 に答える
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);
于 2012-04-26T09:21:04.150 に答える
1

Generic Typed Class の Actual Type 引数を見つける方法があります。

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);
}
于 2012-04-26T09:51:28.447 に答える
0

この行は間違っています:

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

T は TestClass に初期化されるため、これは質問のタイトル、つまり「T はバイトです」と矛盾します。

1 つのアイデアは、配列を List<T> に変更することです。

于 2012-04-26T09:14:52.367 に答える