I'm playing with some functional like programming. And having issues with some pretty deeply nested generics. Here's my SCCE that fails, with an abstract class involved:
public abstract class FooGen<IN, OUT> {
OUT fn2(IN in1, IN in2) { // clever? try at a lazy way, just call the varargs version
return fnN(in1, in2);
}
abstract OUT fnN(IN...ins); // subclasses implement this
public static void main(String[] args) {
FooGen<Number, Number> foogen = new FooGen<Number, Number>() {
@Override Number fnN(Number... numbers) {
return numbers[0];
}
};
System.out.println(foogen.fn2(1.2, 3.4));
}
}
This dies with a
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Number;
However, for a non-abstract FooGen, it works fine:
public class FooGen<IN, OUT> {
OUT fn2(IN g1, IN g2) {
return fnN(g1, g2);
}
OUT fnN(IN...gs) {
return (OUT)gs[0];
}
public static void main(String[] args) {
FooGen<Number,Number> foogen = new FooGen<Number,Number>();
System.out.println(foogen.fn2(1.2, 3.4));
}
}
This prints 1.2. Ideas? It seems like somewhere Java has lost track of the generics. This is pushing the limits of my generics knowledge. :-)
(Added in response to answers)
First, thanks for the upvotes, and to Paul and Daemon for their helpful answers.
Still wondering why it works as Numbers in the 2nd version, I had an insight. As a Thought Experiment, let's add a .doubleValue() somewhere. You can't. In the code itself the variables are INs, not Numbers. And in the main() it's merely declaring the type, FooGen<Number,Number> but there's no place there to add code.
In Version #2, it really isn't "working" as Numbers. Internally, with erasure, everything is Objects, as explained by Paul and Daemon, and, looking back sheepishly, well understood by myself. Basically, in this complex example, I got overexcited and mislead by the <Number> declaration.
Don't think I'll bother with a workaround. The whole idea was to be lazy. :-) For efficiency I created parallel interfaces and code that take primitive doubles (and ints), and there this trick works just fine.