Having some idea of type erasure, I would think this cast would not compile or work at runtime:
public class GenericDatumReader<D> implements DatumReader<D> {
...
@SuppressWarnings("unchecked")
public D read(D reuse, Decoder in) throws IOException {
return (D) read(reuse, actual, expected != null ? expected : actual, in);
}
However, it works!
How does the program know at runtime what D
is?
EDIT
I wrote a simple test:
1 public class Main {
2
3 public static class Something<D> {
4
5 private Object getObj() { return new Object(); }
6 private String getStr() { return new String("hello"); }
7
8 public <D> D get(boolean str) {
9 return (D) (str ? getStr() : getObj());
10 }
11 }
12
13 public static void main(String[] args) {
14 Something<String> something = new Something<>();
15 String str = something.get(true);
16 String notStr = something.get(false);
17 }
18 }
Without the (D)
cast, this doesn't compile:
Main.java:9: error: incompatible types: bad type in conditional expression
return (str ? getStr() : getObj());
^
String cannot be converted to D
where D is a type-variable:
D extends Object declared in method <D>get(boolean)
Main.java:9: error: incompatible types: bad type in conditional expression
return (str ? getStr() : getObj());
^
Object cannot be converted to D
where D is a type-variable:
D extends Object declared in method <D>get(boolean)
2 errors
With the (D)
cast I get just an unchecked warning but it compiles. However, at runtime:
$ java Main
Exception in thread "main" java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.String
at Main.main(Main.java:16)