【问题标题】:The concatenation of chars to form a string gives different results连接字符以形成字符串会产生不同的结果
【发布时间】:2014-01-27 17:48:26
【问题描述】:

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

ret += ... ; // returns numbers

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

下面的代码复制了字符:

doubleChar("The") → "THhee"

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;
}

【问题讨论】:

    标签: java string char concatenation


    【解决方案1】:

    下面表达式的结果

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

    是字符串连接的结果。 The Java language specification states

    字符串连接的结果是一个String对象的引用 那是两个操作数字符串的连接。那些角色 左边的操作数在右边的字符之前 新创建的字符串中的操作数。

    结果

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

    是加法运算符应用于两种数字类型的结果。 The Java language specification states

    二元 + 运算符在应用于两个操作数时执行加法 数字类型,产生操作数的总和。 [...] 数字操作数上的加法表达式的类型是 promoted 其操作数的类型。

    在这种情况下

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

    变成一个int,包含两个char 值的总和。然后将其连接到ret


    您可能还想了解复合赋值表达式+=

    E1 op= E2 形式的复合赋值表达式是等价的 到E1 = (T) ((E1) op (E2)),其中TE1的类型,除了E1 只评估一次。

    换句话说

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

    等价于

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

    【讨论】:

    • 但是他在做ret += str.charAt,其中res是一个字符串。
    • @MxyL 在第二个表达式中,在应用+ 之前,将作为一个整体评估右侧。结果是char,它是两者的总和。
    • @MxyL 另外,对于添加剂+The type of an additive expression on numeric operands is the promoted type of its operands.
    • 我看到的另一个要点是加法运算符是从左到右关联的。所以str.charAt(i) + str.charAt(i) + ret 也会以数字形式添加字符。
    【解决方案2】:

    在您的第一个示例中,您明确添加了一个字符串作为第一个术语。这迫使第二个和第三个任期也被提升为字符串。在第二种情况下,您要添加两个字符(然后将它们附加到字符串中) - 在分配之前它不会提升为字符串。您可以通过使用 Character.toString()String.valueOf() 来明确表达

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

    【讨论】:

      【解决方案3】:

      第一个例子

      从语义上来说,我想说我们正在查看arithmetic promotion 在工作中。注意第一个例子:

      String + char + char
      

      由于算术提升,这两个char 值被提升String 值,因此类型变为:

      String + String + String
      

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

      第二个例子

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

      char + char
      

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

      额外阅读

      关于算术提升的一些注意事项可以在here找到。

      关于表达式求值的一些说明可以在here找到。

      【讨论】:

        【解决方案4】:

        来自Java specification

        15.26.2。复合赋值运算符

        E1 op= E2 形式的复合赋值表达式等价于E1 = (T) ((E1) op (E2)),其中TE1 的类型,但E1 只计算一次。

        因此,+= 运算符具有对目标类型的内置转换。

        相比之下,clause for simple assignment says:

        15.26.1。简单赋值运算符 =

        如果不能通过赋值转换(第 5.2 节)将右侧操作数的类型转换为变量的类型,则会发生编译时错误。

        这里,

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

        被视为字符串连接。

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

        被视为加法运算。

        【讨论】:

          【解决方案5】:

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

          这是因为 ret 是字符串 snd 它与其他字符连接。

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

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

          希望它能消除你的困惑。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-10-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-03-08
            • 2015-01-09
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多