Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why don't you get a compiler error when assign raw types to generic types?

Tags:

java

generics

I have been looking at OJCPA code snippets and I am confused why the compiler does not throw an error at the following code.

List l = new ArrayList();
l.add("a");
l.add("b");
l.add(1);

List<String> strList = new ArrayList<>();
strList = l; //#1 - Why does the assignment compile?

for(String s: strList) {
      System.out.println(s); //#2 - It makes sense that it then throws a ClassCastException
}

I thought that the compiler would see List l as a raw type and because generics are invariant it would produce a compiler error, as it is not of type List< String >.

Thanks for you help.

like image 360
binarycreations Avatar asked Dec 13 '15 12:12

binarycreations


People also ask

What does the compiler do for you when you use generic types?

A Java compiler applies strong type checking to generic code and issues errors if the code violates type safety. Fixing compile-time errors is easier than fixing runtime errors, which can be difficult to find. Elimination of casts. Enabling programmers to implement generic algorithms.

Why is a raw type unsafe in Java?

The warning shows that raw types bypass generic type checks, deferring the catch of unsafe code to runtime. Therefore, you should avoid using raw types. The Type Erasure section has more information on how the Java compiler uses raw types.

Why is raw type allowed in Java?

When generics were introduced into Java, several classes were updated to use generics. Using these class as a "raw type" (without specifying a type argument) allowed legacy code to still compile. "Raw types" are used for backwards compatibility.

What is generic type erasure?

Type erasure is a process in which compiler replaces a generic parameter with actual class or bridge method. In type erasure, compiler ensures that no extra classes are created and there is no runtime overhead.


1 Answers

It is allowed for backwards compatibility.

Suppose that you are calling a legacy method that returns a List of Strings, but it was written before generics were added to Java, so it returns a raw List.

You'd want this line to pass compilation :

List<String> strList = someOldMethodThatReturnsRawList();

Otherwise you'll have to keep using the raw List type in your new code in order to call that method.

like image 151
Eran Avatar answered Nov 15 '22 18:11

Eran