Created
May 9, 2012 14:34
-
-
Save iande/2644926 to your computer and use it in GitHub Desktop.
Why generic type checking is slightly different...
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Box<T> { | |
private T whatsInTheBox; | |
// Creates a new box that holds nothing of value | |
public Box() { this(null); } | |
// Creates a new box that holds the given T instance. | |
public Box(T store) { | |
this.set(store); | |
} | |
// Gets the T instance stored in the box | |
public T get() { return this.whatsInTheBox; } | |
// Stores a T instance in the box | |
public void set(T store) { | |
this.whatsInTheBox = store; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Note: this code is not valid, just meant to serve as an illustration | |
// of why type checking seems to differ when passing around Generics. | |
public class GenericBomb { | |
public static void takeANumber(Number n) { | |
// This is fine because `doubleValue` is declared in the `Number` class. | |
double dVal = n.doubleValue(); | |
// This is not fine because `compareTo` is from the `Integer` class, | |
// and this method sees `n` only as a `Number`. | |
n.compareTo(new Integer(3)); | |
} | |
public static void stuffDoubleInBox(Box<Number> box) { | |
// This code is valid, a "Box that holds a Number" can "hold" an | |
// instance of Double without any problem. However, if the compiler | |
// allowed all of this code to compile, it would blow up at runtime | |
// because we're trying to stuff a `Double` instance into a box that | |
// holds an `Integer` instance. | |
box.set(new Double(3.0)); | |
} | |
public static void stuffNumberInBox(Number n, Box<Number> box) { | |
// This code is also valid, but if the compiler allowed it, it | |
// would blow up at runtime because we're trying to stuff a `Float` | |
// instance into a box that holds an `Integer` instance. | |
box.set(n); | |
} | |
public static void main(String[] args) { | |
Integer myInt = new Integer(4); | |
// myBox is an instance of `Box` that "holds" an instance of `Integer` | |
Box<Integer> myBox = new Box<Integer>(); | |
// Even though we are passing an `Integer` instance, the method sees it as a `Number` instance. | |
takeANumber(myInt); | |
// Even though we are passing a "Box that holds an Integer", the method would see it as | |
// a "Box that holds a Number" (if the compiler allowed this sort of thing.) | |
stuffDoubleInBox(myBox); | |
// And again, this isn't allowed because of how the type system handles Generics. | |
stuffNumberInBox(new Float(0.3f), myBox); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment