字符连接形成一个string给出不同的结果

为什么,当我使用下面的操作来总结字符时,是否返回数字而不是字符? 它不应该给出相同的结果吗?

ret += ... ; // returns numbers ret = ret + ...; // returns chars 

下面的代码重复字符:

doubleChar(“The”)→“TThhee”

 public String doubleChar(String str) { String ret = ""; for(int i = 0; i < str.length(); i++) { ret = ret + str.charAt(i) + str.charAt(i); // it concatenates the letters correctly //ret += str.charAt(i) + str.charAt(i); // it concatenates numbers } return ret; } 

以下expression式的结果

 ret + str.charAt(i) + str.charAt(i); 

是string连接的结果。 Java语言规范说明

string连接的结果是对两个操作数string串联的String对象的引用。 左侧操作数的字符位于新创build的string中右侧操作数的字符之前。

结果

 str.charAt(i) + str.charAt(i); 

是加法运算符应用于两种数字types的结果。 Java语言规范说明

二进制+运算符在应用于数字types的两个操作数时执行加法,产生操作数的总和。 […]数字操作数上的加法expression式的types是其操作数的升级types。

在这种情况下

 str.charAt(i) + str.charAt(i); 

成为一个int保存两个char值的和。 然后连接到ret


您可能也想知道关于复合赋值expression式+=

E1 op= E2的复合赋值expression式等价于E1 = (T) ((E1) op (E2)) ,其中TE1的types,只是E1只计算一次。

换一种说法

 ret += str.charAt(i) + str.charAt(i); 

相当于

 ret = (String) ((ret) + (str.charAt(i) + str.charAt(i))); | ^ integer addition | ^ string concatenation 

在你的第一个例子中,你明确地添加一个string作为第一个术语。 这迫使第二和第三届也被提升为string。 在第二种情况下,您要添加两个字符(然后将其附加到string) – 直到赋值后才会将其提升为string。 你可能已经明确,通过使用Character.toString()或String.valueOf()像这样

 ret += Character.toString(str.charAt(i)) + String.valueOf(str.charAt(i)); 

第一个例子

从语义上讲,我会说我们正在研究arithmetic promotion 。 注意第一个例子:

 String + char + char 

由于算术推广,这两个char被提升为 String值,所以types变成:

 String + String + String 

+被重载,因为所有操作数都是Stringtypes,所以执行连接。

第二个例子

在第二个例子中,与所有赋值一样,我们首先评估=运算符的右边,我们有什么?

 char + char 

该字符被解释为它的数值,因为没有String引起提升,并且我们有一个数字加法,然后被附加到String

额外阅读

算术推广的一些注意事项可以在这里find。

expression评估的一些注意事项可以在这里find。

从Java规范 :

15.26.2。 复合分配算子

E1 op= E2的复合赋值expression式等价于E1 = (T) ((E1) op (E2)) ,其中TE1的types,只是E1只计算一次。

所以+=操作符有一个内置的转换到目标types。

相比之下, 简单分配的条款说 :

15.26.1。 简单的作业操作员=

如果右操作数的types不能通过赋值转换(§5.2)转换为variables的types,则会发生编译时错误。

这里,

  ret = ret + str.charAt(i) + str.charAt(i); 

被视为string连接。

 ret += str.charAt(i) + str.charAt(i); 

被视为适应性操作。

ret = ret + str.charAt(i)+ str.charAt(i); // //正确地连接字母

这是因为ret是string,它与其他字符连接。

ret + = str.charAt(i)+ str.charAt(i); //它连接数字

这是因为编译器首先计算'str.charAt(i)+ str.charAt(i)',这可能会导致一个数字,然后将它与ret连接起来。 所以基本上我们评估左边,然后分配它。

希望它消除你的困惑。