Fundamentals (Docs)



As you already know, it's possible to assign an object of one type to an object of another type provided that the 
types are compatible. For example, you can assign an Integer to an Object, since Object is one of Integer's 

	Object someObject = new Object();
	Integer someInteger = new Integer(10);
	someObject = someInteger; // OK

But Integer is also a kind of Number, so the following code is valid as well:

	public void someMethod(Number n){
	    // method body omitted 
	someMethod(new Integer(10)); // OK
	someMethod(new Double(10.1)); // OK

The same is also true with generics. You can perform a generic type invocation, passing Number as its type 
argument, and any subsequent invocation of add will be allowed if the argument is compatible with Number:

	Box<Number> box = new Box<Number>();
	box.add(new Integer(10)); // OK
	box.add(new Double(10.1)); // OK

Now consider the following method:

	public void boxTest(Box<Number> n){
	    // method body omitted 

What type of argument does it accept? By looking at its signature, we can see that it accepts a single argument 
whose type is Box<Number>. But what exactly does that mean? Are you allowed to pass in Box<Integer> or 
Box<Double>, as you might expect? 
The answer is "no", because Box<Integer> and Box<Double> are not subtypes of Box<Number>.

	public class BoxDemo {
	    public static void main(String[] args) {
		Box<Number> boxN = new Box<>();
		Box<Integer> boxI = new Box<>();
		Box<Double> boxD = new Box<>();
		BoxDemo bx = new BoxDemo();
		bx.boxTest(boxN); // compile OK
		bx.boxTest(boxI); // compile error
		bx.boxTest(boxD); // compile error
	    public void boxTest(Box<Number> box) {
		// ...