Java String类如何重写+;操作人员

Java String类如何重写+;操作人员,java,string,object,Java,String,Object,为什么在Java中,当字符串是一个类时,您可以使用+运算符添加字符串?在String.java代码中,我没有找到此运算符的任何实现。这个概念违反了面向对象吗?这是Java编译器的特性,它检查+运算符的操作数。并根据操作数生成字节码: 对于String,它生成concat字符串的代码 对于数字,它生成代码来添加数字 这是Java规范所说的: 运算符+和-称为加法运算符。 加法表达式: 乘法表达式 加法表达式+乘法表达式 加法表达式-乘法表达式 加法运算符具有相同的优先级,并且在语法上是相同的

为什么在Java中,当字符串是一个类时,您可以使用+运算符添加字符串?在
String.java
代码中,我没有找到此运算符的任何实现。这个概念违反了面向对象吗?

这是Java编译器的特性,它检查
+
运算符的操作数。并根据操作数生成字节码:

  • 对于String,它生成concat字符串的代码
  • 对于数字,它生成代码来添加数字
这是Java规范所说的:

运算符+和
-
称为加法运算符。 加法表达式: 乘法表达式 加法表达式+乘法表达式 加法表达式-乘法表达式

加法运算符具有相同的优先级,并且在语法上是相同的 左关联(它们从左到右分组)。如果其中一种类型
+
运算符的操作数为
字符串
,则该操作为字符串串联

否则,
+
运算符的每个操作数的类型必须是 可转换为原始数字类型(§5.1.8),或发生编译时错误

在任何情况下,二进制
-
运算符的每个操作数的类型都必须是 可转换为基本数字类型的类型(§5.1.8),或 发生编译时错误


+
操作符通常在编译时被
StringBuilder
替换。有关这一点的更多详细信息,请参见此项。

Java语言为字符串连接运算符(+)和其他对象到字符串的转换提供了特殊支持。字符串连接是通过
StringBuilder
(或
StringBuffer
)类及其
append
方法实现的。

首先(+)被重载而不是被重写


Java语言为字符串提供了特殊支持 已为Java字符串重载的连接运算符(+) 对象

  • 若左侧操作数是字符串,则它用作串联

  • 如果左侧操作数是整数,则它用作加法运算符


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

    int x=15;
    String temp="x = "+x;
    
    编译器转换
    “x=“+x编码到
    StringBuilder
    内部,并使用
    .append(int)
    将整数“添加”到字符串中

    任何类型都可以通过字符串转换转换为字符串类型

    原始类型T的值x首先转换为参考值 好像通过将其作为参数提供给适当的类实例 创建表达式(§15.9):

    • 如果T是布尔值,则使用新的布尔值(x)
    • 如果T是char,则使用新字符(x)
    • 如果T是byte、short或int,则使用新的整数(x)
    • 如果T长,则使用新的长(x)
    • 如果T为浮动,则使用新的浮动(x)
    • 如果T是双精度的,则使用新的双精度(x)
    然后将该引用值逐字符串转换为类型 转换

    现在只需考虑参考值:

    • 如果引用为null,则将其转换为字符串“null”(四个ASCII字符n、u、l、l)
    • 否则,转换就好像是通过调用引用对象的toString方法(不带参数)来执行的;但是 如果调用toString方法的结果为null,则 改为使用字符串“null”
    toString方法由原始类对象定义 (§4.3.2). 许多类会覆盖它,特别是布尔字符, 整数、长、浮点、双精度和字符串

    有关字符串转换上下文的详细信息,请参见§5.4

    字符串连接优化: 实现可以选择执行转换和串联 在一个步骤中避免创建然后丢弃中间 字符串对象。以提高重复字符串的性能 连接时,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
    
    进入

    换句话说,字符串连接中的运算符
    +
    实际上是更详细的
    StringBuilder
    习惯用法的简写

    字符串类如何重写+运算符


    没有。编译器完成了这项工作。严格地说,编译器为字符串操作数重载+运算符。

    当应用于
    字符串时,
    +
    运算符的含义是由语言定义的,正如大家已经写过的那样。因为你似乎没有觉得这足够有说服力,所以考虑一下:

    int、float和double都有不同的二进制表示形式,因此在位操作方面,添加两个int与添加两个float是不同的操作:对于int,可以逐位添加,携带一个位并检查溢出;对于浮动,必须分别处理尾数和指数

    因此,原则上,“加法”取决于na
    cip+ciop; 
    
    new StringBuilder(cip).append(ciop).toString();