繁体   English   中英

Java泛型无法编译

[英]Java Generics won't compile

public class GenMethodDemo{

        public GenMethodDemo(){
            Sum.<Integer,Integer,Integer>sum(1,2);       
        }

        public static void main(String args[]){
            new GenMethodDemo();
        }
    }

    class Sum{

     public static final <S extends Number,Z extends S,X extends S> S sum(Z v1,X v2){
            System.out.printf("v1=%1$s,v2=%2$s%n",v1.getClass(),v2.getClass());
            return v1+v2;
        }

错误获得:

error: bad operand types for binary operator '+'
        return v1+v2;
  first type:  Z
  second type: X
  where Z,S,X are type-variables:
    Z extends S declared in method <S,Z,X>sum(Z,X)
    S extends Number declared in method <S,Z,X>sum(Z,X)
    X extends S declared in method <S,Z,X>sum(Z,X)
1 error

无法理解我在做什么错? 如果我使用Integer更改SZX-一切正常,但为什么不能使用泛型代码编译?

重构代码为:

public class GenMethodDemo2{

    public GenMethodDemo2(){
        Sum.<Integer>sum(1,2);        
    }

    public static void main(String args[]){
        new GenMethodDemo2();
    }
}
class Sum{

    public static final <S extends Integer> S sum(S v1,S v2){
        System.out.printf("v1=%1$s, v2=%2$s%n",v1.getClass(),v2.getClass());
        return v1+v2;
    }
} 

error: incompatible types: int cannot be converted to S
        return v1+v2;
  where S is a type-variable:
    S extends Integer declared in method <S>sum(S,S)
1 error

因此,S应该是Integer或Integer类的任何子类,以任何方式肯定都可以+其值。 这个版本有什么问题?

S extends Integerint cannot be converted to S ,怎么可能呢? 为什么没有自动装箱?

您遇到的问题是,因为没有+的定义运营商Number ,只对特定的子类Number 例如, +是为IntegerDouble等定义的,但不是BigIntegerBigDecimalNumber任何其他非标准实现的。

没有通用的加法的好方法。 您最终不得不提供BinaryOperator<S> ,因此您的代码如下所示:

sum(1, 2, Integer::sum);
sum(1.0, 2.0, Double::sum);

这不仅仅是冗长的:

1 + 2
1.0 + 2.0

编译器需要为v1v2编译时类型定义+ 它们在运行时是否为Integer (或其他任何值)无关紧要:是否允许+由编译器决定,因为它必须能够保证该方法对于任何参数都是类型安全的。

上面的方法编译为此:

 public static final Number sum(Number v1, Number v2){
   System.out.printf("v1=%1$s,v2=%2$s%n",v1.getClass(),v2.getClass());
   return v1+v2;
 }

这称为类型擦除

如果未为Number定义+ ,则不允许使用此代码。

对于所有内置的通用解决方案Number扩展:

public static Number sum(final Number a, final Number b) {
    return new BigDecimal(a.toString()).add(new BigDecimal(b.toString()));
}

(注意:不能保证toString()会给出一个可由BigDecimal解析的String ,但据我所知,它对所有内置的JDK Number扩展都是如此。)

如果您想做一些更聪明的事情,可以对instanceof进行一些检查,以找到输入的类型并从那里开始工作,但是我尝试过一次,以便在所有Number之间实现Comparable ,而性能也没有比强制转换更好到BigDecimal

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM