I have the following two classes:
public class GenericNumberOperation {
public GenericNumberOperation() {}
public <T extends Number> T getSomeValue (boolean tf) {
T number;
if(tf) {
number = new Double(1.0);
}
else {
number = new Integer(11);
}
return (T) number;
}
}
And:
public class GenericNumberTest {
public GenericNumberTest() {}
public static void main(String[] args) {
GenericNumberOperation gno = new GenericNumberOperation();
Double d = gno.getSomeValue(true);
Integer i = gno.getSomeValue(false);
}
}
When I run the test, everything is hunky-dory. If I change the type parameterization to:
public <T> T getSomeValue(boolean tf)
The compiler complains, reporting:
error: incompatible types Integer cannot be converted to T number = new Integer(11); where T is a type variable T extends Object declared in method getSomeValue(boolean)
It complains similarly about the Double. Why?
EDIT: I made a mistake. This is actually the code that works.
public class GenericNumberOperation {
public GenericNumberOperation() {}
public <T extends Number> T getSomeValue (boolean tf) {
Number number;
if(tf) {
number = new Double(1.0);
}
else {
number = new Integer(11);
}
return (T) number;
}
}
And now I understand what @Sotirios was getting at.
Forget about what you're trying to use this for. We're only going to look at this from a language perspective.
The declaration
public <T extends Number> T getSomeValue (boolean tf) {
defines a new type T that is bounded by Number. That means that a caller can only bind Number or any subtype of Number to T when invoking the method. Within the method, you don't know what that type might be.
You therefore can't do
T number = new Double(1.0);
because you don't know that T is Double. If I invoked the method as
Float f = genOp.getSomeValue(true);
T should have been Float. The compiler can't guarantee type safety and therefore rejects it (the assignment within the method, if it had been allowed, a ClassCastException would have been thrown at runtime). If you use a cast, you're telling the compiler that you're sure about what you're doing. It'll warn you, but it will trust you.
Similarly, the declaration
public <T> T getSomeValue(boolean tf)
defines a new type T that is unbounded. That means that you can bind any type to T, which makes the problem even greater. I can now do
String f = genOp.getSomeValue(true);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With