为什么+在Java中使用Strings?

Java不能执行运算符重载,但+对于StringInteger以及其他一些类都可以正常工作。 这怎么可能?

更新:
为什么这样做?

 Integer i = 4; Integer p = 5; System.out.println(i*p); // prints 20 

+不是运算符重载的示例。 +作为连接运算符算术加法运算符构建在语言中。

这意味着用Java编写程序的人不能重载操作符,但就Java语言的语法而言, +被定义为连接和加法运算符。

编辑

由于自动装箱,它适用于其他类,如IntegerDouble

如果你看一下执行字符串连接的Java程序的字节码,你会看到它创建了StringBuilder并使用了append()方法。 Java编译器看到+运算符并意识到操作数是字符串而不是基本类型(如int )。

如果查看执行整数加法的程序的字节码,您将看到它使用iadd指令执行整数加法。 这是因为编译器意识到+操作的操作数是整数。

对于像Integer i = 4这样的东西,字节码将显示你实际上在做Integer i = Integer.valueOf(4) 。 这称为自动装箱。 稍后,当您执行类似i + p ,其中ip都是Integer类型,生成的字节码将显示您正在执行i.intValue() + p.intValue() ,其中两者的返回类型方法是int (实际的字节码指令再次,是iadd )。

这就是为什么+工作Integer即使它们不是实际的原始类型。

由于autoboxing,它适用于像Integer这样的原始包装器。

它适用于String,因为这是连接字符串的特殊情况 :

Java语言为字符串连接运算符(+)提供特殊支持,并为其他对象转换为字符串。 字符串连接是通过StringBuilder(或StringBuffer)类及其append方法实现的。 字符串转换是通过方法toString实现的,由Object定义并由Java中的所有类inheritance。 有关字符串连接和转换的其他信息,请参阅Gosling,Joy和Steele,Java语言规范。

+是内置操作。 这是一个例外,不是规则。

Java不允许自定义运算符重载,但编译器开发人员仍然可以告诉编译器String1 + String2 == String1String2,并用+运算符替换正确的串联方法调用。

Java语言为字符串连接运算符(+)提供特殊支持,并为其他对象转换为字符串。

 String s = "string 1" + "string 2"; 

实际执行的是

 (new StringBuilder()).append("string 1").append("string 2").toString() 

正如@yan所说,这是例外,而不是规则。 字符串在Java中具有特殊的地位。 Java语言规范的一小部分专门用作+作为字符串连接运算符的角色: §15.18.1 。

关于您的更新,这是另一个特例。 根据具体情况,Java 有时足够聪明,可以在需要String时将非String的内容转换为String 。 其中一个特殊情况是您描述的情况,其中原语出现在需要String 。 首先将基元转换为它们的引用类型 – IntegerDouble和c。 – 然后通过toString()方法进入String

另一种特殊情况是当一个String和一个非String与字符串连接运算符+ ,如JLS§5.4 – 字符串转换中所述 。

为了完整性: +更常见的“将数字加在一起”角色在§15.18, §15.18.2的另一部分中描述- 数字类型的加法运算符(+和 – ) 。