字符串类如何覆盖+运算符?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (17)

为什么在Java中,当String是类时,可以使用+操作符添加String?在String.java代码我没有为这个操作符找到任何实现。这个概念是否违反了对象定向?

提问于
用户回答回答于

让我们看一下以下Java中的简单表达式

int x=15;
String temp="x = "+x;

编译器转换"x = "+x;变成StringBuilder内部和使用.append(int)若要将整数“添加”到字符串中,请执行以下操作。

字符串转换:

任何类型都可以通过字符串转换转换为类型字符串。 首先将原始类型T的值x转换为引用值,就好像将其作为适当的类实例创建表达式的参数一样:

  • 如果T是布尔型,则使用新的布尔(X)。
  • 如果T是char,则使用新字符(X)。
  • 如果T是字节、短或int,则使用新的Integer(X)。
  • 如果T是长的,那么使用新的long(X)。
  • 如果T是浮点数,那么使用新的浮点数(X)。
  • 如果T是双,那么使用新的双(X)。

然后通过字符串转换将此引用值转换为String类型。

现在只需要考虑参考值:

  • 如果引用为NULL,则将其转换为字符串“NULL”(4个ASCII字符n、u、l、l)。
  • 否则,转换就像调用引用对象的toString方法一样不带参数;但是如果调用toString方法的结果为null,则使用字符串“NULL”。

toString方法由原始类对象定义(§4.3.2)。许多类重写它,特别是布尔值、字符、整数、长、浮点、双和字符串。

字符串连接的优化:实现可以选择在一个步骤中执行转换和级联,以避免创建和丢弃中间字符串对象。为了提高重复字符串级联的性能,Java编译器可以使用StringBuffer类或类似的技术来减少通过计算表达式创建的中间字符串对象的数量。 对于基本类型,实现还可以通过直接将原始类型转换为字符串来优化包装器对象的创建。

优化后的版本实际上不会首先进行完整包装的字符串转换。

这是编译器使用的优化版本的一个很好的说明,尽管没有对原语进行转换,在这里可以看到编译器在后台将内容转换为StringBuilder:

这个java代码:

public static void main(String[] args) {
    String cip = "cip";
    String ciop = "ciop";
    String plus = cip + ciop;
    String build = new StringBuilder(cip).append(ciop).toString();
}

生成此-查看两个级联样式如何导致完全相同的字节码:

 L0
    LINENUMBER 23 L0
    LDC "cip"
    ASTORE 1
   L1
    LINENUMBER 24 L1
    LDC "ciop"
    ASTORE 2

   // cip + ciop

   L2
    LINENUMBER 25 L2

    NEW java/lang/StringBuilder
    DUP
    ALOAD 1
    INVOKESTATIC java/lang/String.valueOf(Ljava/lang/Object;)Ljava/lang/String;
    INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
    ALOAD 2
    INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;

    ASTORE 3

    // new StringBuilder(cip).append(ciop).toString()

   L3
    LINENUMBER 26 L3

    NEW java/lang/StringBuilder
    DUP
    ALOAD 1
    INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
    ALOAD 2
    INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;

    ASTORE 4
   L4
    LINENUMBER 27 L4
    RETURN

查看上面的示例以及如何根据给定示例中的源代码生成字节代码,您将能够注意到编译器在内部转换了以下语句

cip+ciop; 

new StringBuilder(cip).append(ciop).toString();

换句话说,操作员+在字符串中,串联实际上是更详细的缩写。StringBuilder成语。

用户回答回答于

检查+接线员。并根据操作数生成字节码:

  • 对于字符串,它生成连接字符串的代码。
  • 对于数字,它生成代码以添加数字。

这就是Java规范的意思:

算子+和-被称为加法算子。加法表达:多重表达添加剂+多重表达添加剂--多重表达---表达--- 加法算子具有相同的优先级,并且在句法上是左结合的(它们从左到右分组).如果+运算符是String**,则操作为字符串连接。**否则,则为+运算符必须是可转换为原始数字类型的类型(§5.1.8),否则会发生编译时错误。在每种情况下,二进制的每个操作数的类型。-运算符必须是可转换为原始数字类型的类型(§5.1.8),否则会发生编译时错误。

扫码关注云+社区