Possible Duplicate:
How to cast generic List types in java?
When this is feasible
Number number = new Integer("");
Why not this ?
List<Number> list = new LinkedList<Integer>();
Possible Duplicate:
How to cast generic List types in java?
When this is feasible
Number number = new Integer("");
Why not this ?
List<Number> list = new LinkedList<Integer>();
This could help :
http://www.ibm.com/developerworks/java/library/j-jtp01255.html
Basically, since you declared a list of Number, the API would allow you to enter any kind of Number in it, including a Number that is not an Integer.
Consider the fact that this works, might give you an idea of what's going on:
List<? extends Number> list = new LinkedList<Integer>();
The extends
indicates the relation between the generic types on each side of the equation.
You're almost there. Type parameters in Java are neither implicitly covariant nor contravariant; that is, they're invariant. You can use bounded wildcards to write almost the same declaration:
final List<? extends Number> number = new LinkedList<Integer>();
Given that your list starts out empty here, and you intend to insert items, you're looking for covariance: namely, that you can insert any item that's of type Number
, such as Integer
. Note that the LinkedList
constructor is intending to lock things down to allow insertions only of type Integer
, and the bound reference number
no longer knows exactly what type of Number
that actual list can accommodate. You get covariant reading from number
, as you'd expect:
final Number n = number.get(0);
But you can't insert a Number
because the the reference's type can't guarantee proper covariance between the element to be inserted and the declared type of the list itself.
number.add(new Integer(0));
That expression doesn't compile; an Integer
is "some kind of Number
", but it's not guaranteed to match "a specific kind of Number
", which could be, say, Double
.
There is a difference between C++ template and Java generics. Java's generics are a compiler time type checking. In case of C++, the C++ compiler compiles a whole new class depending upon the template. IN case of Java, it is only Compile time type checking and this information is removed on the generated byte code. Hence generics are not covariant (they do not know who is the parent and who is the child).
I always find it useful to give an example of why this isn't allowed. Consider the following code:
// Create and initialise a list of integers
List<Integer> myIntegerList = new ArrayList<Integer>();
myIntegerList.add(1);
// Some other stuff, possibly passing the list through method calls
List<Number> numbers = myIntegerList;
numbers.add(2.0d); // Legal, since this is a list of double
// And at some point later...
myIntegerList.get(1); // throws ClassCastException because element is a Double
Basically, if generics were covariant, then they wouldn't be worth anything as you would have no guarantee that the generics would limit the list to the supposed contents (which is their whole raison d'etre, after all). The way that you expected things to work, any list could be passed into a List<Object>
variable and then any objects at all could be legally put inside it.
As shown above, you can use wildcards to convey the fact that it can be some kind of list of numbers; but then you cannot add elements to the list because it cannot be guaranteed that the elements are of the correct type.
This question goes beyond any specifics of Java Generics. It's more about subtyping in general.
Number has only read methods, while List has write methods too. Suppose for a minute that Number has write methods too
class Number
void set(Number that){...}
Integer i = 1;
Float f = 2.5;
Number n = i;
n.set(f); // same as i.set(f), that's trouble
In this experiment, Integer should not be a subtype of Number anymore, because it cannot support a method in Number.
Another example, Square and Rectangle. Which one should be the super type, which one should be the sub type? It really depends on what methods they have.
Coming from our mathematical training we "intuitively" think of those objects as immutable. Even List feels like an immutable sequence of objects. "Subtype" is often equated to "sub set" in mathematics.
In imperative programming that's not the case, and that creates a lot of mental conflicts.