Search code examples
javaarraysgenericsgettersetter

Why does setter method in generic array work(JAVA)?


Basically why can we assign the value of generic array inside the class using setter method but it throws runtime error whenever we try to access it outside of the generic class?

class Demo<T>{
    T d[]=(T[])new Object[3];
    T x;
    int l=0;
    void setD(T x){
        d[l++]=x; //Why does this work?
    }
    void getD(int x){
        System.out.println(d[x]); //Why does this work too? as i cant print in main class directly
    }

}

public class Main<T> {

    public static void main(String[] args) {

        Demo<Integer> de=new Demo<>();
        de.x=7; //This doesnt throw any error

        //de.d[0]=3; //This throws runtime error. Runtime error is given below.. I understand why this doesn't work 
//but i wanted to know why does that setter method work as this line of code seems similar to that of setter method
        de.setD(3);

        de.getD(0);

    }
}

Exception in thread "main" java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [Ljava.lang.Integer; ([Ljava.lang.Object; and [Ljava.lang.Integer; are in module java.base of loader 'bootstrap') at com.company.Main.main(Main.java:34)

Why is it this way?


Solution

  • I think that's because of type erasure. Look at this line.

    Demo<Integer> de=new Demo<>();
    de.d[0]=3; //java knows, that de.d should be Integer[], but it actually is Object[]
    

    Here, because generic parameter is specified, java expects that de.d is Integer[]. But it actually is Object[]. And java tries to treat array of Objects as array of Integers.

    To do that, java has to cast Object[] to Integer[] . And it throws an exception. That same exception is thrown if you do the following

    Integer[] ints = (Integer[])new Object[10];
    

    And inside you class Type Erasure is applied. So, java treat T as Object in runtime. And so this method

    T d[]=(T[])new Object[3];
    void setD(T x){
        d[l++]=x; //Why does this work?
    }
    

    puts an x, which is Object to array of Objects. There's no problem casting Integer to Object and there's no need to cast Object[] to Integer[] . So, everything works. The code in the method is equivalent to the following

    Object d[]= (Object[])new Object[3];
    void setD(Object x){
        d[l++]=x; // x is Integer here
    }