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());