是否可以在Java中为数字框类型编写通用的+1方法?

pol*_*nts 5 java generics bounded-wildcard

这不是功课.

第1部分

是否可以编写泛型方法,如下所示:

<T extends Number> T plusOne(T num) {
    return num + 1; // DOESN'T COMPILE! How to fix???
}
Run Code Online (Sandbox Code Playgroud)

没有使用一堆instanceof和演员,这可能吗?


第2部分

以下3种方法编译:

Integer plusOne(Integer num) {
    return num + 1;
}   
Double plusOne(Double num) {
    return num + 1;
}
Long plusOne(Long num) {
    return num + 1;
}
Run Code Online (Sandbox Code Playgroud)

是否有可能编写约束仿制药TInteger,DoubleLong

pol*_*nts 6

第1部分

对此没有令人满意的解决方案,因为java.lang.Number没有指定任何对计算a的后继有用的东西Number.

您必须instanceof检查数字框类型,并专门处理每个案例.还需要注意的是,你可能会得到一个instanceof Number这是没有数字框中显示类型,例如BigInteger,AtomicLong和潜在的未知子类Number(如Rational,等).

第2部分

在这里看起来很欺骗.这3种方法可能看起来很相似,但是自动装箱/拆箱隐藏了它们在字节码级别实际上非常不同的事实:

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
Run Code Online (Sandbox Code Playgroud)

不仅是3个方法调用不同xxxValue(),并valueOf()在不同类型的方法,但该指令推恒定1到堆栈也不同(iconst_1,dconst_1,和lconst_1).

即使可以绑定泛型类型<T=Integer|Long|Double>,这三种方法也不能泛化为一种方法,因为它们包含非常不同的指令.


Jim*_*ley 5

并非所有Number的子类都可以自动装箱.例如,BigDecimal无法自动装箱.因此"+"运算符不适用于它.