Reputation: 221
I know that , every generic type variable replaced to upper bound that has been determined from the generic definition in the start of method "type-parameter section".
this is from Deitel book
Actually, all type parameters are replaced with the so-called upper bound of the type parameter, which is specified in the type-parameter section.
according to that , this subcode must be true
public static <E extends Number> void A( )
{
E x= new Double(2.2);
}
but the compiler tell me is compilation error in E x= new Double(2.2);, although this must be true because the double is number .
I know how to process and solve the problem in general by casting , but I ask why this occur ?
Upvotes: 4
Views: 1501
Reputation: 7507
Just because E
is a number doesn't mean that it is a Double
.
Think of it like this, what if E was an Integer. E is still a Number, but now you are assigning a Double to an Integer. So the casting behavior is consistent, Number can be all sorts of different Types, and so could E.
EDIT for Op: The Deitel statement is still correct, If you were assigning the Double to a Number or to an Object then you wouldn't need casting. In this case though, E is not assigning "upwards" it's assigning "laterally" between two possible different Number types. What if E was a Short, or an Integer, in these cases you wouldnt expect to be able to assign them a Double without casting.
Upvotes: 6
Reputation: 65821
And yet this works perfectly!
public static <E extends Number> void A() {
E x = (E)new Double(2.2);
}
Be nice to your compiler and it will be nice to you. All you need to do is tell it what you mean.
And - of course - since we are actually lying to our compiler now it lets us do scary stuff like:
public class Test {
public static <E extends Number> E makeOne() {
E x = (E) new Double(2.2);
return x;
}
// Some real compiler abuse.
public void test() {
Integer one = Test.<Integer>makeOne();
Double two = Test.<Double>makeOne();
Number three = Test.<Double>makeOne();
}
}
To our readers at home ... this is not how Generics should be used.
Oh - and by the way, the reason you are seeing your problem is that you are mismatching types without casting.
Your problem is a conceptual one. The type passed in a Generic clause <E extends Number>
is not a place-holder for the type you finally decide to use. You are not just delaying your decision about which type to use. You are making a promise to only use types matching the clause and, if you ever break that promise the compiler must warn you.
The reason your code is not accepted is because you are doing just that, you are breaking that promise. You are saying that although the caller can use any Number
you will use a specific Number
(Double
) so you are breaking the rules you have laid down for yourself and the compiler is telling you off.
Upvotes: 3
Reputation: 795
All you know is that E
extends Number
. Type E
could be Integer
, which is also a subclass of Number
.
Wouldn't make much sense to assign assign new Double(2.2)
to a variable named x
of type Integer
.
Upvotes: 0
Reputation: 13907
When you specify E extends Number
, this means E
is any subtype of Number
, or Number
itself. For example, E
could be an Integer
, Long
, Double
, etc. This is why your code does not compile - if E
was Integer
, for example, it would be wrong to be able to assign a Double
to the variable of type Integer
.
Upvotes: 3