I was answering Applying functions of various types to a value question yesterday while I noticed something quite strange.
I'm able to define a collection as being of type O even though its real type is T.
This can probably be explained by the fact that I'm using raw types.
However, the most surprising part is that I'm able to consume from this collection which is a List<FileInputStream> even though it is obvious it is a List<Integer>.
Hereunder is the code in question
public static void main(String[] args) {
String value = "a string with numb3r5";
Function<String, List<String>> fn1 = List::of;
Function<List<String>, String> fn2 = x -> x.get(0);
Function<String, List<Integer>> fn3 = x -> List.of(x.length());
InputConverter<String> converter = new InputConverter<>(value);
List<FileInputStream> ints = converter.convertBy(fn1, fn2, fn3);
System.out.println("ints = " + ints);
System.out.println("ints.get(0) = " + ints.get(0));
System.out.println("ints.get(0).getClass() = " + ints.get(0).getClass());
}
public static class InputConverter<T> {
private final T src;
public InputConverter(T src) {
this.src = src;
}
@SuppressWarnings({"unchecked", "rawtypes"})
public <R> R convertBy(Function... functions) {
Function functionsChain = Function.identity();
for (Function function : functions) {
functionsChain = functionsChain.andThen(function);
}
return (R) functionsChain.apply(src);
}
}
And here is the result
ints = [21]
ints.get(0) = 21
Exception in thread "main" java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.io.FileInputStream (java.lang.Integer and java.io.FileInputStream are in module java.base of loader 'bootstrap')
at Scratch.main(scratch_8.java:18)
Why is it possible to consume from this collection ?
I noticed the follwing don't throw an exception when consuming it
System.out.println("String.valueOf(ints.get(0)) = " + String.valueOf(ints.get(0)));
System.out.println("((Object) ints.get(0)).toString() = " + ((Object) ints.get(0)).toString());
However the following does
System.out.println("ints.get(0).toString() = " + ints.get(0).toString());