hlucasfranca
hlucasfranca

Reputation: 270

Why does Java allow a raw List to be passed to a generic List constructor?

I'm studying for OCA certification and on the ArrayList topic, after making some tests, I came across the following issue:

import java.util.ArrayList;

public class ArrayLists{

    public static void main(String[] args) {

        ArrayList list = new ArrayList(); 

        list.add(1);
        list.add("hi");

        // Passing a non-Generics list to a Generics list
        ArrayList<String> list2 = new ArrayList<>(list); 

        for(int i = 0; i < list2.size(); i++) {
            System.out.println(list2.get(i));
        }

        // error, cannot cast Integer to string
        for(String s : list2) { 
            System.out.println(s); 
        }

    }
}

Why does Java compile this behavior, since I'll get a runtime error running the program?

Upvotes: 0

Views: 115

Answers (1)

Anton Krosnev
Anton Krosnev

Reputation: 4132

This allows the legacy code (written before Java 5 existed) could still be used in newly written code without modification.
The declaration of the list uses Raw type

    ArrayList list = new ArrayList();

Raw types show up in legacy code because lots of API classes (such as the Collections classes) were not generic prior to JDK 5.0. When using raw types, you essentially get pre-generics behavior — a Box gives you Objects.

That is why it is possible to add Integer and String. It is similar to this declaration:

ArrayList<Object> list = new ArrayList<Object>();

but with type checking disabled and just a warning is shown:

Type Safety: The expression of type ArrayList needs uncheck conversion to conform to Collection < ? extends String>

for the line:

    ArrayList<String> list2 = new ArrayList<>(list); 

Upvotes: 1

Related Questions