directly access to generic array does not work

jwkoo :

I was wondering how to initialize the generic array in the constructor.

After searching on google, I wrote the code below.

public class Test<E>{
    private E[] mData;

    public Test(){
        mData = (E[])new Object[100];
    }

    public void put(E data, int index){
        mData[index]=data;
    }

    public E get(int index){
        return mData[index];
    }

    public static void main(String[] args){
        Test<Integer> t1 = new Test<>();
        t1.put(100, 0);
        System.out.println(t1.get(0)); // 100
    }
}

The output of the above code is expectedly 100, but if I access the generic array directly, it gives an error.

The code looks like below.

public class Test<E>{
    private E[] mData;

    public Test(){
        mData = (E[])new Object[100];
    }

    public static void main(String[] args){
        Test<Integer> t1 = new Test<>();
        t1.mData[0] = 100;
        System.out.println(t1.mData[0]);
        // java.lang.ClassCastException error
    }
}

The above code just gives me an ClassCastException error.

I have no idea what's the differences between those code I have uploaded.

Any help might really be appreciated.

iluxa :

The important thing here is that type of mData is always Object[], even if it's masquerading as E[].

In your first example, the following happens under the hood:

    public E get(int index){
        Object x = mData[index];
        E result = (E) x;
        return result;
    }

In the second example however,

// ClassCast
Integer[] tempArray = t1.mData;
System.out.println(tempArray[0]);

If you actually want your array to be of type E[], use Array.newInstance(), but that does introduce an unnecessary argument to the constructor.

Your approach is more user-friendly (ArrayList, for example, does the same thing), just make sure to not expose the underlying array directly.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=308992&siteId=1