如何声明变量x和y,使得x+=y会导致编译错误而x=x+y不会?

55

我在面试中遇到了这个问题,但是无法想出解决方案。我知道相反的情况可以像 Java中的“+=”运算符是什么意思? 中所示那样实现。

问题如下:

..... x = .....;
..... y = .....;

x += y; //compile error
x = x + y; //works properly

有趣的是,Java是否允许使用加号进行字符串拼接?我不懂Java,但这似乎是一种可能性。 - Jess
104
多么毫无意义的面试问题。 - Jonathon Faust
@Jonathon 完全同意。如果你想要开发编译器或 JVM 实现,这些细节是很重要的,但对于一般程序员来说,这只是需要查看规范然后忘记的事情。 - G_H
8
取决于提问者是否想知道受访者是否知道答案,这是无用的。但是,观察某人如何应对愚蠢的面试问题,或者看看他们如何在类似问题上大声思考,也许带有提示,以了解他们是否具备任何语言技能,这些是有价值的。 - Ed Staub
21
让我们看看他是否会去Stack Overflow上问问题。如果他这样做了,那么让我们雇用他,因为这是在实际项目中工作时正确和适当的行为! - Jean-François Corbett
显示剩余2条评论
4个回答

55

尝试这段代码

Object x = 1;
String y = "";

x += y; //compile error
x = x + y; //works properly

我不太确定为什么这能工作,但编译器报错:

参数类型为Object,String时,运算符+=未定义

所以我猜第二行代码是在 Object 上调用了 toString 方法。

编辑:

这很有意义,因为对于一个普通的 Object,+= 运算符是没有意义的。在我的示例中,我将 int 强制转换为 Object,但这取决于 x 的类型为 Object:

Object x = new Object();

只有当x是Object时才有效,所以我认为更确切的说是String是Object的直接子类。这个方法在x + y时会失败:

它仅适用于x是Object, 因此我认为String更准确的是直接继承自Object。但是这将无法处理x + y的情况:

Foo x = new Foo();

对于我尝试过的其他类型。


1
谢谢。我在Eclipse中尝试了一下,就像你说的那样。但是我发现在NetBeans中它只是编译而没有任何错误。这是否意味着这不是Java的普遍问题,而是取决于编译器? - knshn
6
如果x是Object类型而y是String类型,则应该编译x+=y。请参见http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7058838. - x22
1
是的,这取决于编译器,因为问题是如何以这种方式引起编译器错误。 Java语言本身可能不允许发生这种情况,但编译器可能没有正确实现规范。 因此,这并不是一个清晰的问题,并且是一个相当可怕的面试问题。 - skynet
这是一个有点棘手的JAVA问题...最好称之为魔法问题;-) - Vishal

3
无法实现。
X x = ...;
Y y = ...;

x += y;         //1
//equivalent to
x = (X) (x+y);  //2

x = x+y;        //3

假设 x+y 的类型是 Z。#2 需要从 Z 到 X 进行强制类型转换;#3 需要从 Z 到 X 进行赋值类型转换。"强制类型转换比赋值类型转换更具包容性"(1)。因此,只要 #3 合法,#2 就合法,#1 也合法。
反过来,可能出现 #1 合法但 #3 不合法的情况,例如:
    byte x = 0;
    int y  = 1;
    x+=y;     // ok, x=(byte)(x+y), cast int to byte is allowed.
    x = x+y;  // error, assign int to byte

这些信息毫无用处,这是Java的一个缺陷,导致出现了如此令人惊讶的差异。
(1)http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.5

4
可以,参考@Craigy的回答。 - Paul Wagland

2
int  i = 5;
String s = "a";
System.out.println(i+=s);  //Error
System.out.println(i+s);   // No error

基本上,适用于任何对象或任何非字符串原始类型和字符串组合。

我想知道是哪家公司? :)


这并不完全等价,因为在这里它们被转换为字符串,而在第二种情况下使用i = i + s会将它们转换为int,从而导致编译错误。 - skynet

1

这个东西并不总是会给你编译错误。

如果你正在做这样的事情:

class A{
public static void main(String args[]){
    String x = "10";
    String y = "s";
    x += y;
    System.out.println(x);
}
}

它会很好地工作

即使你这样做

class A{
public static void main(String args[]){
    int x = 10;
    float y = 11.5F;
    x += y;
    System.out.println(x);
}
}

它将正常工作。

但是,如果您使用x和y两种不同类型的变量,例如:

class X{
 }
class A{
public static void main(String args[]){
    X x = new X();
    float y = 11.5F;
    x += y;
    System.out.println(x);
}
}

在这种情况下,它将无法编译。
*即使您可以将任何int、float等与String连接起来。

但在这种情况下,x + y 也会失败,而不仅仅是 x += y - nikhil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接