Java Reference
In-Depth Information
There are some obvious problems with the method signature. The parameters n1 and n2 could be of any
parameterized type of Wrapper<T> class. For example, the following call would be a valid call for the sum() method:
// Try adding an Integer and a String
sum(new Wrapper<Integer>(new Integer(125)), new Wrapper<String>("Hello"));
Computing the sum of an Integer and a String does not make sense. However, the code will compile and you
should be ready to get some runtime exceptions depending on the implementation of the sum() method. You must
restrict this kind of code from compiling. It should accept two Wrapper objects of type Number or its subclasses, not just
anything. Therefore, you do know the upper bound of the type of the actual parameter that the Wrapper object should
have. The upper bound is the Number type. If you pass any other type, which is a subclass of the Number type, it is fine.
However, anything that is not a Number type or its subclass type should be rejected at compile time. You express the
upper bound of a wildcard as
<? extends T>
Here, T is a type. <? extends T> means anything that is of type T or its subclass is acceptable. Using your upper
bound as Number , you can define your method as
public static double sum(Wrapper<? extends Number> n1, Wrapper<? extends Number> n2){
Number num1 = n1.get();
Number num2 = n2.get();
double sum = num1.doubleValue() + num2.doubleValue();
return sum;
}
The following snippet of code inside the method compiles fine:
Number num1 = n1.get();
Number num2 = n2.get();
No matter what you pass for n1 and n2 , they will always be assignment-compatible with Number because the
compiler will make sure that the parameters passed to the sum() method follow the rules specified in its declaration of
<? extends Number> . The attempt to compute the sum of an Integer and a String will be rejected by the compiler.
Consider the following snippet of code:
Wrapper<Integer> intWrapper = new Wrapper<Integer>(new Integer(10));
Wrapper<? extends Number> numberWrapper = intWrapper; // Ok
numberWrapper.set(new Integer(1220)); // A compile-time error
numberWrapper.set(new Double(12.20)); // A compile-time error
Can you figure out the problem with this snippet of code? The type of numberWrapper is <? extends Number> ,
which means it can refer to (or it is assignment-compatible with) anything that is a subtype of the Number class. Since
Integer is a subclass of Number , the assignment of intWrapper to numberWrapper is allowed. When you try to use the
set() method on numberWrapper , the compiler starts complaining because it cannot make sure at compile time that
numberWrapper is a type of Integer or Double , which are subtypes of a Number . Be careful with this kind of compiler
error when working with generics. On the surface, it might look obvious to you and you would think that code should
compile and run fine. Unless the compiler makes sure that the operation is type-safe, it will not allow you to proceed.
After all, compile-time and runtime type-safety is the primary goal of generics!
 
Search WWH ::




Custom Search