Reputation: 270
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
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