How to build generic arrays-- JAVA programming ideas 54

Posted by anindya23 on Tue, 21 Sep 2021 23:10:00 +0200

Today, let's talk about how to create a generic array?

Some people may say that this is not simple. Just T[] array = new T[size]?

Unfortunately, the compiler will prompt that generics cannot be instantiated directly.

Let's change our thinking. First create an Object array and then convert it to the corresponding generic. Is that ok?

public class GenericArrayTest<T> {

    private T[] array;

    public GenericArrayTest(int size) {
        this.array = (T[]) new Object[size];
    }

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

    public void put(int index, T element) {
        array[index] = element;
        System.out.println("Subscript:"+index+",Save element:"+element);        
    }

    public T get(int index) {
        System.out.println("Get subscript:" + index + " Element:" + array[index]);
        return array[index];
    }

    public static void main(String[] args) {
        GenericArrayTest<String> genericArrayTest = new GenericArrayTest<String>(10);
        String[] array = genericArrayTest.getArray();
    }

}

Although the above code has been compiled, it actually can't run. Running the code will throw a type conversion exception. Due to the influence of generic erasure, all generic parameters without defined boundaries are erased as Object by default. Also, because the data structure of the array requires that the type of its stored data be determined during creation, and its stored data type cannot be changed later, Object [] cannot be converted to String [] (for the introduction of generic erasure, please refer to What is generic erasure?).

Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
	at mtn.baymax.charpter15.GenericArrayTest.main(GenericArrayTest.java:40)

In order to verify that T [] is Object [] during runtime, we can successfully put any type into the array in GenericArrayTest by bypassing the limitation of the compiler through reflection and calling the put() method.

    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException,
            IllegalAccessException {
        GenericArrayTest<String> genericArrayTest = new GenericArrayTest<String>(10);
        Class clazz = genericArrayTest.getClass();
        Method put = clazz.getMethod("put", int.class, Object.class);
        put.invoke(genericArrayTest, 1,123);
        put.invoke(genericArrayTest, 1,4.5F);
        put.invoke(genericArrayTest, 1,5.24D);
    }
Subscript: 1,Storage element: 123
 Subscript: 1,Storage element: 4.5
 Subscript: 1,Storage element: 5.24

So how exactly should generic arrays be created?

Although a generic type will be converted to an Object during runtime, we can pass a Class Object into the constructor and restore the specific type through Class to create the corresponding array. The code is as follows.

public class GenericArrayTest<T> {

    private T[] array;

    public GenericArrayTest(Class<T> tClass, int size) {
        this.array = (T[]) Array.newInstance(tClass, size);
    }

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

    public void put(int index, T element) {
        array[index] = element;
        System.out.println("Subscript:" + index + ",Save element:" + element);
    }

    public T get(int index) {
        System.out.println("Get subscript:" + index + " Element:" + array[index]);
        return array[index];
    }

    public static void main(String[] args) {
        GenericArrayTest<String> genericArrayTest = new GenericArrayTest<String>(String.class, 10);
        genericArrayTest.put(0, "a");
        genericArrayTest.put(1, "b");
        genericArrayTest.put(2, "c");
        String[] array = genericArrayTest.getArray();
        for (int i = 0; i < array.length; i++) {
            genericArrayTest.get(i);
        }
    }

}
Subscript: 0,Save element: a
 Subscript: 1,Save element: b
 Subscript: 2,Save element: c
 Get subscript: 0 element: a
 Get subscript: 1 element: b
 Get subscript: 2 element: c
 Get subscript: 3 element: null
 Get subscript: 4 element: null
 Get subscript: 5 element: null
 Get subscript: 6 element: null
 Get subscript: 7 element: null
 Get subscript: 8 element: null
 Get subscript: 9 element: null

Summary

To create a generic array, you need to know the following:

1. Generic types with undefined boundaries will be erased as objects during operation.

2. The type of array cannot be changed after creation.

3. The specific type erased by the generic can be obtained by passing in the Class object in the generic.

This sharing is over. I hope this article will help you. If you can light the like button below, I'd be grateful. Thank you for your [spiritual support].

If you have any questions, you are also welcome to communicate with me. If there are deficiencies, you are also welcome to correct!

Topics: Java