如何解决在使用泛型时出现的“bad operand for binary operator ‘+’”错误?

huangapple go评论89阅读模式
英文:

How to solve "bad operand for binary operator '+' " when used with Generics?

问题

这是我的代码:

class MyExample {

    public static <T, R> R myMethod(T x, R y) {
        R z = x + y; // 错误发生在这里
        
        return z;
    }

    public static void main(String args[]) {
        Integer val = 10;
        String str = "Hello World!";
        System.out.println(val + str); // 这将打印预期结果
        System.out.println(myMethod(10, " Hello World!"));
    }

}

这段代码出现错误:

二元运算符 + 的操作数有问题

当我在主块内使用 + 连接 val 和 str 时,它在主块内工作得很好,但在 myMethod 内部不起作用。

我不明白为什么会发生这种情况。

英文:

here is my code :

class MyExample {

    public static &lt;T,R&gt; R myMethod(T x,R y){
        R z= x+y;// error occurs here
        
        return z;
    }

    public static void main(String args[])
    {
        Integer val = 10;
        String str=&quot;Hello World!&quot;;
        System.out.println(val+str);// this prints the expected result
        System.out.println(myMethod(10,&quot; Hello World!&quot;));
    }

}

This code gives error:

> bad operand for binary operator +

When I concat val and str with + it works fine within the main block, But not inside the myMethod.

I don't understand why it happens.

答案1

得分: 4

Java不支持运算符重载。操作符`+`在八种原始类型(`char`、`byte`、`short`、`int`、`long`、`float`和`double`)中的七种上有定义,以及在`String`上也有定义。

类型`T`和`R`是无界的,因此它们被擦除为`Object`。由于`+`在`Object`上没有定义,编译器生成编译错误。

`System.out.println(val + str);`之所以有效,是因为表达式的右侧(`str`)是一个`String`,因此编译器试图将左侧(`val`)转换为`String`。每个类(至少是隐式地)从`Object`继承,因此每个类都有一个实例方法`toString()`,用于将其实例转换为`String`。

[GoslingInterview]: http://www.gotw.ca/publications/c_family_interview.htm
[TypeErasure]: https://docs.oracle.com/javase/tutorial/java/generics/erasure.html
[JLS-8.1.4]: https://docs.oracle.com/javase/specs/jls/se14/html/jls-8.html#jls-8.1.4
[ObjectToStringAPI]: https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Object.html#toString()
[JLS-5.1.11]: https://docs.oracle.com/javase/specs/jls/se14/html/jls-5.html#jls-5.1.11
英文:

Java does not support operator overloading. The operator + is defined on seven of the eight primitive types (char, byte, short, int, long, float and double), as well as on String.

The types T and R are unbounded, therefore they are erased with Object. Since + is not defined on Object, the compiler generates a compiler error.

System.out.println(val + str); works because the right side (str) of the expression is a String, hence the compiler tries to convert the left side (val) into a String. Every class (at least implicitly) inherits from Object, therefore every class has an instance method toString() that is used to convert its instances to Strings.

答案2

得分: 1

正如许多人已经指出的那样,Java 不允许运算符重载,因此你必须使用泛型方法,在其中定义了 +TR 被擦除为对象,意味着它们被视为对象,因为TR 之间唯一的共同点是对象中可用的属性,记住编译器中的TR 可以是任意的任意类型。

下面的代码并不是我建议使用的内容,更像是一种 hack,但是它可以让你编译通过,然而在运行时可能会出现许多错误,请自行注意

class MyExample {

    public static <T, R> R myMethod(T x, R y){
        return (R) (x.toString() + y.toString());
    }
    public static void main(String args[])
    {
        Integer val = 10;
        String str="Hello World!";
        System.out.println(val+str);// this prints the expected result
        System.out.println(myMethod(10," Hello World!"));
        System.out.println(myMethod("Hello World!", 10));
    }
}

这种方法是通过使用其中定义了+的8种类型之一来实现的。在上面的例子中,我们使用了 String,因为任何对象都有一个字符串表示,可以通过toString()方法获得,然后将类型强制转换回返回类型R

现在,我想完全明确,这里发布的代码只是一个让你能够编译的 hack,请不要在任何重要的代码中使用这段代码。

所以说实话,我建议你询问你想要实现的行为,而不是询问如何修复你当前的解决方案,因为这只会导致极其高级的代码,而且谁知道呢,也许你需要更简单的东西。

英文:

As many people point out already Java does not allow operator overloading so you are bound to use the generic method where + is define. T and R are erased with object meaning they are treated as object because the only common things between T and R are properties available in object, remember T and R for the compiler could be any arbitrary types.

The code below is not something i will suggest using, is more of a hack than anything else but it will let you compile, however is prone to many errors in runtime consider yourself warned

class MyExample {

    public static &lt;T ,R &gt; R myMethod(T x, R y){
        return (R) (x.toString() + y.toString());
    }
    public static void main(String args[])
    {
        Integer val = 10;
        String str=&quot;Hello World!&quot;;
        System.out.println(val+str);// this prints the expected result
        System.out.println(myMethod(10,&quot; Hello World!&quot;));
        System.out.println(myMethod(&quot;Hello World!&quot;, 10));
    }
}

the way that works is by using one of the 8 types where + is defined. In the case above we are using String because any object has an string representation with the toString() method and then casting the type back to the return type R

Now I just to be completely clear the code posted here is just a hack to let you compile please do not use that code for any important code.

So to be honest I would recommend you to rather ask for the behavior you are trying to archive and not about how to fix your current solution since this will only lead to extremely advance code and who knows maybe you need something way simpler.

huangapple
  • 本文由 发表于 2020年9月3日 00:52:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/63710124.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定