3

I have read through different articles which talks about why we cannot create generic array in java, but still I don't quite understand why.

For example, it this post, it assumed if generic array initialisation is possible, there will be casting issue after erasure. You can find the details in section 2. Considerations When Using Generic Arrays. In simplest term, the generic array becomes an Object Array after erasure, and if the generic type is String, java will fail to cast Object[] to String[].

However, I created a generic class with a simple function,

// Test.java
public class Test<T> {
    public T[] getStrArr(T[] arr) {
        return arr;
    }
}

//Main.java
public static void main(String[] args) {
       Test<String> test = new Test<>();
        String[] strArr = test.getStrArr(new String[]{"A", "B", "C"});
}

After erasure, the getStringArr should return Object[], and it is able to cast to String[] without any problem.

Another stackoverflow post stated that:

arrays (unlike generics) contain, at runtime, information about its component type. So you must know the component type when you create the array. Since you don't know what T is at runtime, you can't create the array.

but erasure will change T into Object type, so compiler can create array with Object type.

There are other posts with similar explanation but cannot really resolve my doubt.

Please help!

HKIT
  • 628
  • 1
  • 8
  • 19
  • 1
    *After erasure, the getStringArr should return Object[]* -> no it doesn't, because it does **not** create a generic array. You're the one passing in a `String[]` so the `getStrArr` doesn't have to do any array creation at all – Lino Sep 25 '21 at 10:51
  • @Lino, thanks for the reply. the return type of getStringArr is T[], according to erasure => Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. so the return type should becomes Object[]. I am referencing https://docs.oracle.com/javase/tutorial/java/generics/erasure.html – HKIT Sep 25 '21 at 10:54
  • When using generics the compiler "cheats" by adding implicit casting. Because you pass a `String[]` into the method, and then return it directly, the final cast (to `String[]`) when assigning the return value of `getStrArr()` to `strArr` will work, because the returned value **is** a `String[]` – Lino Sep 25 '21 at 12:00
  • @Lino, you are right, I missed the very basic thing. Thanks – HKIT Sep 25 '21 at 12:47

1 Answers1

1

After erasure, the getStringArr should return Object[], and it is able to cast to String[] without any problem.

Return type of the getStrArr, after type erasure, would be Object[] but, in your code, it is returning arr which is of type String[]. That is why there is not ClassCastException in your code.

Consider the following method (suppose generic arrays were allowed):

public T[] foo() {
    return new T[5];                  
} 

After type erasure, new T[5] will be replaced by new Object[5]. Now if the calling code calls this method as:

String[] strArr = obj.foo();

It will lead to ClassCastException because Object[] cannot be casted to String[].

Yousaf
  • 27,861
  • 6
  • 44
  • 69
  • thanks a lot for the response. Clear explanation on the first part, understood now, thanks a lot. For the second part, I know it is a problem to create array with generic class, just as you explained. But it is not quite related to using generic parameter to create array, which is new T[]. So after your explanation, my understanding is we cannot use new T[] because it is not possible to do the casting. Hope I got it right. – HKIT Sep 25 '21 at 12:46
  • I have removed the second part related to parameterized arrays. Generic arrays cause problems related to casting and that is why they are not allowed. – Yousaf Sep 25 '21 at 13:29