Java 泛型无法编译

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

不明白我做错了什么?如果我将 SZX 更改为 Integer - 一切正常,但为什么使用泛型代码无法编译?


重构代码为:


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 Integer但是int cannot be converted to S,怎么可能呢?为什么没有自动装箱?


慕哥6287543
浏览 130回答 2
2回答

牧羊人nacy

您遇到的问题是因为没有为+定义运算符Number,只有 的特定子类Number。例如,+是为 等定义的Integer,Double但不是BigInteger,BigDecimal或 的任何其他非标准实现Number。没有很好的方法来进行泛型加法。您最终不得不提供一个BinaryOperator<S>,因此您的代码如下所示:sum(1,&nbsp;2,&nbsp;Integer::sum); sum(1.0,&nbsp;2.0,&nbsp;Double::sum);这比仅仅更冗长:1&nbsp;+&nbsp;2 1.0&nbsp;+&nbsp;2.0需要+为 和 的编译时类型定义编译v1器v2。它们是否在运行时(或其他什么)并不重要Integer:是否允许+由编译器决定,因为它必须能够保证该方法对于任何参数都是类型安全的。上面的方法编译成这样:&nbsp;public&nbsp;static&nbsp;final&nbsp;Number&nbsp;sum(Number&nbsp;v1,&nbsp;Number&nbsp;v2){ &nbsp;&nbsp;&nbsp;System.out.printf("v1=%1$s,v2=%2$s%n",v1.getClass(),v2.getClass()); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;v1+v2; &nbsp;}这称为类型擦除。如果+没有为 a 定义Number,则不允许使用此代码。

慕神8447489

作为所有内置Number扩展的通用解决方案:public&nbsp;static&nbsp;Number&nbsp;sum(final&nbsp;Number&nbsp;a,&nbsp;final&nbsp;Number&nbsp;b)&nbsp;{&nbsp; &nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;BigDecimal(a.toString()).add(new&nbsp;BigDecimal(b.toString())); }(注意:不能保证toString()会给出String可解析的,BigDecimal但据我所知,它适用于所有内置的 JDKNumber扩展。)如果你想做一些更聪明的事情,你可以做一些检查instanceof以找到输入的类型并从那里开始工作,但我试过一次Comparable在所有Numbers 之间实现并且性能并不比强制转换为BigDecimal.
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java