Consider the following code (the two questions are inside the code):
import java.util.*;
public class Tree<T> {
private T info;
private List<Tree<? extends T>> children = new ArrayList<Tree<? extends T>>();
public Tree<? extends T> getChildren(int n) {
return children.get(n);
}
public void addChildren(Tree<? extends T> children) {
this.children.add(children);
}
public static void main(String[] args) {
Tree<?> b2; // so b2 is a reference of a Tree of unknown type
b2 = new Tree<Number>(); /* to allow b2 to call addChildren() with Tree<? extends Number> aguments */
b2.addChildren(new Tree<Number>()); // 1) why it doesn't work ?
b2.addChildren(new Tree<Integer>()); // neither does this one!
b2.addChildren(new Tree<>()); // 2) but with diamond <> it works ?
}
}
- Why does
b2.addChildren(new Tree<Number>())not work? - But it works with diamond <>
b2.addChildren(new Tree<>()). Which type list the compiler uses inside the diamond <>?
The problem is that you have declared
b2to have a type ofTree<?>.The problem is clearer if you rewrite your main method as two methods:
Even though you created a
new Tree<Number>(), you are immediately discarding that information. Your code is only remembering thatb2contains some unknown type of Tree, sinceTree<?>means "some type of Tree but I don't know what type."Since we don't know what the Tree's type is, how do we know if it's safe to call
addChildren(new Tree<Number>()), ornew Tree<Integer>()ornew Tree<String>()ornew Tree<JTable>()? The compiler has no idea. You may remember what you put in there, but the type ofb2doesn't carry that information, so the compiler doesn't have any way to know.