javagenericscastingerasure

Same erasure but not the same type.


How can it be the case that ArrayList<Class<?>> has the same erasure of ArrayList<Object> but cannot be cast to it?

My code is currently switching between two eclipse errors.

GenericExclusiveSelectionPanel transport = 
                new GenericExclusiveSelectionPanel(StringConstants.TRANSPORT,
                    (ArrayList<Object>)TransportManager.getInstance().getTransportTypes());

which shows:

Cannot cast from ArrayList<Class<Transportable>> to ArrayList<Object>

If I remove the cast however and create a constructor:
GenericExclusiveSelectionPanel(String, ArrayList<Class<Transportable>>)

I get the eclipse error that:

Erasure of method GenericExclusiveSelectionPanel(String, 
   ArrayList<Class<Transportable>>) is the same as another method in type 
   GenericExclusiveSelectionPanel

It then highlights the constructor (below) as the conflicting constructor.

GenericExclusiveSelectionPanel(String title, ArrayList<Object> arrayList)

Solution

  • It would be easier to understand why this happens if we first understand what type erasure means with respect to Generics in Java. Take a look at type erasure from the Oracle documentation before proceeding.

    Now that you know what type erasure means, lets look at what the the Oracle documentation has to say about generics.

    It should be clear from the documentation that the primary goal of Generics was to provide tighter compile time checks. It would be quite a contradiction if the compiler did not enforce a check on casting with generics. For the sake of discussion, consider hypothetically that the following statements were allowed :

    List<String> strings = new ArrayList<String>();//1
    strings.add("123");//2
    List<Object> objects = strings;//3
    objects.add(1);//4
    

    If the compiler did not restrict the assignment at step 3, you would be able to add an Integer to a list of String objects. What good are Generics in the first place if the compiler doesn't complain about the assignment at step 3 which in turn allows us to go ahead with step 4?

    Similarly, while ArrayList<Class<Transportable>> and ArrayList<Object> have the same erasure, the compiler is right in complaining about their assignment as explained above. In conclusion, restricting these casts with Generics is as important as restricting constructors/methods with the same erasure.