简体   繁体   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 get: 错误获得:

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

Can't understand what i'm doing wrong? 无法理解我在做什么错? If i change SZX with Integer - all works fine but why with generics code won't compile? 如果我使用Integer更改SZX-一切正常,但为什么不能使用泛型代码编译?

Refactored code to: 重构代码为:

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

So, S supposed to be an Integer or any subclass of Integer class, in any way it definitely should be possible to + their values. 因此,S应该是Integer或Integer类的任何子类,以任何方式肯定都可以+其值。 What's wrong with this version? 这个版本有什么问题?

S extends Integer but int cannot be converted to S , how it could be? S extends Integerint cannot be converted to S ,怎么可能呢? Why there is no autoboxing? 为什么没有自动装箱?

The problem you're experiencing is because there is no + operator defined for Number , only specific subclasses of Number . 您遇到的问题是,因为没有+的定义运营商Number ,只对特定的子类Number For example, + is defined for Integer , Double etc, but not BigInteger , BigDecimal or any other non-standard implementation of Number . 例如, +是为IntegerDouble等定义的,但不是BigIntegerBigDecimalNumber任何其他非标准实现的。

There is no good way to do generic addition. 没有通用的加法的好方法。 You end up having to provide a BinaryOperator<S> , so your code looks like: 您最终不得不提供BinaryOperator<S> ,因此您的代码如下所示:

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

which is more verbose than just: 这不仅仅是冗长的:

1 + 2
1.0 + 2.0

The compiler requires + to be defined for the compile-time types of v1 and v2 . 编译器需要为v1v2编译时类型定义+ It doesn't matter if they are Integer (or whatever) at runtime: the decision as to whether to allow the + is made by the compiler, because it has to be able to guarantee that the method is type-safe for any arguments. 它们在运行时是否为Integer (或其他任何值)无关紧要:是否允许+由编译器决定,因为它必须能够保证该方法对于任何参数都是类型安全的。

The method above is compiled to this: 上面的方法编译为此:

 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;
 }

This is called type erasure . 这称为类型擦除

If + isn't defined for a Number , this code isn't allowed. 如果未为Number定义+ ,则不允许使用此代码。

As a general solution for all inbuilt Number extensions: 对于所有内置的通用解决方案Number扩展:

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

(Note: there's no guarantee that toString() will give a String which is parseable by BigDecimal but it does for all the inbuilt JDK Number extensions to the best of my knowledge.) (注意:不能保证toString()会给出一个可由BigDecimal解析的String ,但据我所知,它对所有内置的JDK Number扩展都是如此。)

If you wanted to do something more clever, you could do some checks with instanceof to find the types of the inputs and work from there, but I tried that once for implementing Comparable between all Number s and the performance wasn't any better than casting to BigDecimal . 如果您想做一些更聪明的事情,可以对instanceof进行一些检查,以找到输入的类型并从那里开始工作,但是我尝试过一次,以便在所有Number之间实现Comparable ,而性能也没有比强制转换更好到BigDecimal

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

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