Part 1
There is no satisfactory solution for this, since java.lang.Number
doesn't specify anything that would be useful to compute the successor of a Number
.
You'd have to do instanceof
checks for the numeric box types, and handle each case specially. Note also that you may get an instanceof Number
that's none of the numeric box types, e.g. BigInteger
, AtomicLong
, and potentially unknown subclasses of Number
(e.g. Rational
, etc).
Part 2
Look is very deceiving, here. The 3 methods may look alike, but autoboxing/unboxing hides the fact that they're actually very different at the bytecode level:
Integer plusOne(Integer);
Code:
0: aload_1
1: invokevirtual #84; //int Integer.intValue()
4: iconst_1
5: iadd
6: invokestatic #20; //Integer Integer.valueOf(int)
9: areturn
Double plusOne(Double);
Code:
0: aload_1
1: invokevirtual #91; //double Double.doubleValue()
4: dconst_1
5: dadd
6: invokestatic #97; //Double Double.valueOf(double)
9: areturn
Long plusOne(Long);
Code:
0: aload_1
1: invokevirtual #102; //Long Long.longValue()
4: lconst_1
5: ladd
6: invokestatic #108; //Long Long.valueOf(long)
9: areturn
Not only are the 3 methods invoking different xxxValue()
and valueOf()
methods on different types, but the instruction to push the constant 1
to the stack is also different (iconst_1
, dconst_1
, and lconst_1
).
Even if it's possible to bind a generic type like <T=Integer|Long|Double>
, the 3 methods are not genericizable into one method since they contain very different instructions.