First some code (Java 7) created just to illustrate my questions.
import java.util.*;
class Generics101 {
public static void addTrue(List list) {
list.add(true);
}
public static void main(String[] args) {
List<Integer> testList = new ArrayList<>();
addTrue(testList);
System.out.println(testList.get(0));
// testList.add(true); // will not compile when uncommented
}
}
I have the following two questions:
In addTrue
method Eclipse hints that it does not like raw types
. When I try to change method parameters to use a wildcard List<?> list
it won't compile. I looked through Generics Tutorial but could not find the answer. What am I missing here and where should I read about it?
The same tutorial states that "Generics were introduced to the Java language to provide tighter type checks at compile time..." I understand that due to type erasure
such enforcement can't happen at run-time and so my above code compiles and runs. It will trigger compiling error if the commented line is uncommented, so I assume that tighter type checks
are in force within the same method. What is the exact scope for such enforcement? How is it formally defined?
When I try to change method parameters to use a wildcard List list it won't compile.
It wouldn't compile, because you can't add anything in a List<?>
. Because you don't know which type of List
is actually coming. For example, take your current case only. You are passing a List<Integer>
. It would successfully be passed to List<?>
. No issues. But you are adding true
, a boolean
type to it. If compiler allowed that, it would throw ClassCastException
at runtime. So, it isn't allowed.
so I assume that tighter type checks are in force within the same method. What is the exact scope for such enforcement?
No, it's not like that. It is not that the type checks are done under a certain scope. It's enforced wherever generics are used. Your current code won't compile if used with proper generics, because you are trying to add a boolean
type to a List<Integer>
. Why would you expect that to work?
Try changing your method to a generic method, and you'll see that it would fail to compile:
public static <T> void addTrue(List<T> list) {
list.add(true); // Won't compile
}
I looked through Generics Tutorial but could not find the answer. What am I missing here and where should I read about it?
Well, that is the standard tutorial from Oracle. And that is where you should read. Apart from that, you can also go through a really nice collection of tutorial on generics at Java Generics FAQs - Angelika Langer.