0
public class GenericDemo<T> {

    T data[] = (T[])new Object[1];

    public static void main(String[] args) {

        GenericDemo<String> gdStr = new GenericDemo<>();
        gdStr.data[0] = new String("Hello"); //Runtime Class cast exception


        GenericData<Integer> dataInt = new GenericData<>();
        dataInt.setObj(new Integer(25));
        System.out.println(dataInt.getObj());

        GenericData<String> dataString = new GenericData<>();
        dataString.setObj("Hello World");
        System.out.println(dataString.getObj());
    }
}

class GenericData<T> {
    private T obj;

    public void setObj(T obj) {
        this.obj = obj;
    }
    public T getObj(){
        return obj;
    }
}

In the above code runtime error --> gdStr.data[0] = new String("Hello"); but compiles just fine. the same runs fine when value is set and called in getter/setter. May I know the problem here.

ernest_k
  • 44,416
  • 5
  • 53
  • 99
  • 1
    Does this answer your question? [How to create a generic array in Java?](https://stackoverflow.com/questions/529085/how-to-create-a-generic-array-in-java) – almac777 Mar 12 '22 at 06:35

1 Answers1

0

The cast (T[])new Object[1] is theoretically incorrect if T is anything other than Object -- the object's actual runtime class is Object[], which is not an instance of String[], Integer[], or whatever. It doesn't immediately cause any exceptions because inside an instance of GenericDemo, it doesn't know what T is, so it can't enforce that data is an instance of T[] -- it can only enforce that data is an instance of the erasure of T[], which is Object[], and that is fine.

So as long as you keep this lie inside of an instance of GenericDemo, nothing bad happens. However, if you expose the (incorrect) claim that data has type T[] to outside the instance, to a place which has a specific idea of what T is, then they can have an expectation on the type of data that is incorrect. That is what happens here. In the static method main, it has a GenericDemo<String> gdStr, so it can expect that gdStr.data is an instance of String[] (and the compiler can insert a cast to it), which it is not. This is why there is an exception.

GenericData doesn't have any unsafe casts, so it doesn't have this problem. But let's say you do the same type of unsafe cast, and unsafe holding of an Object[] in a T[] variable, in a class GenericData2, but you do not expose this variable to outside the instance in any way, only dealing with it with the instance's methods, then you will also not get any exception:

class GenericData2<T> {
    private T[] data = (T[])new Object[1];

    public void setObj(T obj) {
        this.obj[0] = obj;
    }
    public T getObj(){
        return obj[0];
    }
}
newacct
  • 119,665
  • 29
  • 163
  • 224