Return T [] (where T is Byte []) in Byte []

I have a Java JUnit 4 test and a generic class that creates a generic array. When I create a method to return this shared array, I get an error message after returning it. It works if I return an ArrayList (where T is an instance of Byte by class) in an ArrayList.

Why is an array of instances created and used (tested on more complex classes), but I canโ€™t return a link to this array?

Error:

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

Grade:

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;
    }
}

Test:

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);
    }

}
+3
source share
4 answers

A โ€œgeneratedโ€ array can be built by reflection:

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

Replace with the Byte.classlink to the desired class. In other words:

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;
    }
}

You can check this out as such:

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<?> .

+5
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

There is a way to find out the Actual Type arguments for a typical typed class.

I just changed the constructor like this for the main class.

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;
} }

And the testing method.

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

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

This line is incorrect:

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

This contradicts the name of your question, i.e. "where T is a byte" since T is initialized to TestClass.

One idea is to change the array in List <T>.

0
source

All Articles