Reputation: 133
This code works, and I dont understand how the list is able to add a raw type box, I thought type erasure will set the type to their indicated bounds. note: Paper class doesn't extends Bakery class.
EDIT: Is my understanding correct? the compiler typecasts the raw box type so that it can be added to the list? does this works only at compile time? so if I tried to get the value at runtime it will throw an exception?
class Violator {
public static List<Box<? extends Bakery>> defraud() {
List<Box<? extends Bakery>> list = new ArrayList<>();
Paper paper = new Paper();
Box box = new Box<>();
box.put(paper);
list.add(box);
return list;
}
}
class Box<T> {
void put(T item) { /* implementation omitted */ }
T get() { /* implementation omitted */ }
}
Upvotes: 2
Views: 164
Reputation: 8345
This code does generate an unchecked conversion warning, as to why its permitted, from Angelika Langer's blog
To facilitate interfacing with non-generic (legacy) code. Raw types are permitted in the language predominantly to facilitate interfacing with non-generic (legacy) code.
If, for instance, you have a non-generic legacy method that takes a
List
as an argument, you can pass a parameterized type such asList<String>
to that method. Conversely, if you have a method that returns aList
, you can assign the result to a reference variable of typeList<String>
, provided you know for some reason that the returned list really is a list of strings.
Your answer lies in Conversely, if you have a method that returns a List
, you can assign the result to a reference variable of type List<String>
. In your case you might have a legacy method that returns a Box
// Legacy code
private Box getBox(){
// returns a Box which satisfy the Box<? extends Bakery>
}
even though the returned result might satisfy the constraint Box<? extends Bakery>
, there is no way to be completely sure, so you are allowed to add that box to your list
Upvotes: 3