Typical Type and Purpose Problems

I know that every typical type variable is replaced with an upper bound, which was determined from the general definition at the beginning of the "type parameter section" method.

this is from Deitelโ€™s book

In fact, all type parameters are replaced by the so-called upper ones associated with the type parameter, which is specified in the type parameter of the section.

according to this, this subcode must be true

public static <E extends Number> void A( ) { E x= new Double(2.2); } 

but the compiler tells me that this is a compilation error in E x = new Double (2.2); although this should be true because double is a number .

I know how to handle and solve the problem as a whole by casting, but I ask, why is this happening?

+4
source share
4 answers

Just because E is a number does not mean it is Double .

Think about it so that if E was integer. E is still a number, but now you are assigning Double Integer. Thus, the casting behavior is consistent, Number can be of all kinds of different types, and therefore E.

EDIT for Op: the Deitel statement is still true. If you assigned Double to a Number or Object, you will not need casting. In this case, however, E does not assign "up", it assigns "in the transverse direction" between two possible different types of numbers. What if E was short or integer, in these cases you did not expect that you could assign them Double without casting.

+6
source

When you specify E extends Number , it means that E is any subtype of Number or Number . For example, E can be Integer , Long , Double , etc. That's why your code does not compile - if E was an Integer , for example, it would be wrong to assign a Double variable of type Integer .

+3
source

And yet it works great!

 public static <E extends Number> void A() { E x = (E)new Double(2.2); } 

Be kind to your compiler, and it will be good for you. All you have to do is say what you mean.

And, of course, since we are actually lying to our compiler, this allows us to do scary things 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(); } } 

For our readers at home ... this is not how generics should be used.

Oh - and by the way, the reason you see your problem is because you don't match types without casting.

Your problem is conceptual. The type passed in the Generic <E extends Number> expression is not a place holder for the type that you finally decided to use. You do not just put off your decision about which type to use. You promise to use only those types that match this sentence, and if you ever break that promise, the compiler should warn you.

The reason your code is not accepted is because you are doing exactly that, you are breaking that promise. You say that although the caller can use any Number , you will use a specific Number ( Double ) to break the rules that you yourself set, and the compiler says you disconnected.

+1
source

All you know is the E extends Number . Type E can be Integer , which is also a subclass of Number .

It makes no sense to assign the assignment of new Double(2.2) variable named x type Integer .

0
source

Source: https://habr.com/ru/post/1483464/


All Articles