String 类如何覆盖 + 运算符? [英] How does the String class override the + operator?

查看:22
本文介绍了String 类如何覆盖 + 运算符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Why in Java you're able to add Strings with the + operator, when String is a class? In theString.java code I did not find any implementation for this operator. Does this concept violate object orientation?

推荐答案

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

Let's look at the following simple expressions in Java

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

编译器在内部将 "x = "+x; 转换为 StringBuilder 并使用 .append(int) 来添加"整数到字符串.

The compiler converts "x = "+x; into a StringBuilder internally and uses .append(int) to "add" the integer to the string.

5.1.11.字符串转换

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

Any type may be converted to type String by string conversion.

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

A value x of primitive type T is first converted to a reference value as if by giving it as an argument to an appropriate class instance creation expression (§15.9):

  • 如果 T 是布尔值,则使用 new Boolean(x).
  • 如果 T 是 char,则使用 new Character(x).
  • 如果 T 是 byte、short 或 int,则使用 new Integer(x).
  • 如果 T 很长,则使用 new Long(x).
  • 如果 T 是浮点数,则使用 new Float(x).
  • 如果 T 是 double,则使用 new Double(x).

然后将这个引用值逐个字符串转换成String类型转换.

This reference value is then converted to type String by string conversion.

现在只需要考虑参考值:

Now only reference values need to be considered:

  • 如果引用为空,则将其转换为字符串空"(四个 ASCII 字符 n、u、l、l).
  • 否则,转换就像是调用被引用对象的 toString 方法而没有参数一样;但如果调用 toString 方法的结果为 null,则改为使用字符串null".

toString方法由原始类Object定义(第 4.3.2 节).许多类覆盖了它,特别是 Boolean、Character、整型、长整型、浮点型、双精度型和字符串.

The toString method is defined by the primordial class Object (§4.3.2). Many classes override it, notably Boolean, Character, Integer, Long, Float, Double, and String.

有关字符串转换上下文的详细信息,请参阅第 5.4 节.

See §5.4 for details of the string conversion context.

15.18.1.

字符串连接的优化:一个实现可以选择执行转换和连接一步避免创建然后丢弃中间体字符串对象.提高重复字符串的性能串联,Java 编译器可以使用 StringBuffer 类或减少中间字符串对象数量的类似技术通过对表达式求值而创建的.

Optimization of String Concatenation : An implementation may choose to perform conversion and concatenation in one step to avoid creating and then discarding an intermediate String object. To increase the performance of repeated string concatenation, a Java compiler may use the StringBuffer class or a similar technique to reduce the number of intermediate String objects that are created by evaluation of an expression.

对于原始类型,实现也可以优化掉通过直接从原语转换来创建包装对象输入字符串.

For primitive types, an implementation may also optimize away the creation of a wrapper object by converting directly from a primitive type to a string.

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

The optimized version will not actually do a full wrapped String conversion first.

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

This is a good illustration of an optimized version used by the compiler, albeit without the conversion of a primitive, where you can see the compiler changing things into a StringBuilder in the background:

http://caprazzi.net/posts/java-bytecode-string-concatenation-and-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();
}

生成这个 - 看看这两种连接样式如何导致完全相同的字节码:

Generates this - see how the two concatenation styles lead to the very same bytecode:

 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

看上面的例子,以及基于给定例子中的源代码的字节码是如何生成的,你会注意到编译器内部已经转换了下面的语句

Looking at the example above and how the byte code based on the source code in the given example is generated, you will be able to notice that the compiler has internally transformed the following statement

cip+ciop; 

进入

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

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

In other words, the operator + in string concatenation is effectively a shorthand for the more verbose StringBuilder idiom.

这篇关于String 类如何覆盖 + 运算符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆