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

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

问题描述

为什么在Java中,当String是类时,你能用+运算符添加字符串?在 String.java 代码中,我找不到此运算符的任何实现。这个概念是否违反了面向对象?

解决方案

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

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

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



5.1.11。字符串转换


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



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




  • 如果T是布尔值,则使用新的布尔值(x)。

  • 如果T是char,然后使用new Character(x)。

  • 如果T是byte,short或int,则使用new Integer(x)。

  • 如果T很长,则使用新的Long(x)。

  • 如果T为float,则使用new Float(x)。

  • 如果T是double,然后使用new Double(x)。



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



现在只需要考虑参考值:




  • 如果参考为null,它被转换为字符串null(四个AS CII字符n,u,l,l)。

  • 否则,转换的执行就好像通过调用没有参数的引用对象的toString方法一样;但是
    如果调用toString方法的结果为null,则使用
    字符串null。



toString方法由原始类Object
(§4.3.2)定义。许多类都覆盖它,特别是布尔值,字符,
整数,长整数,浮点数,双精度和字符串。



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


15.18.1。


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



对于基本类型,实现还可以通过直接从原始
类型转换为字符串来优化包装对象的
创建。


优化后的版本实际上不会先进行完全包装的String转换。



<这是编译器使用的优化版本的一个很好的例证,虽然没有原语的转换,你可以看到编译器在后台将事物更改为StringBuilder:



http://caprazzi.net/posts/java-字节码串级联和 - 的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
LDCcip
ASTORE 1
L1
LINENUMBER 24 L1
LDCciop
ASTORE 2

// cip + ciop

L2
LINENUMBER 25 L2

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

ASTORE 3

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

L3
LINENUMBER 26 L3

新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
返回

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

  cip + ciop; 

进入

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

换句话说,运营商 + in string concatenation实际上是更详细的 StringBuilder idiom的简写。


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?

解决方案

Let's look at the following simple expressions in Java

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

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

5.1.11. String Conversion

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

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):

  • If T is boolean, then use new Boolean(x).
  • If T is char, then use new Character(x).
  • If T is byte, short, or int, then use new Integer(x).
  • If T is long, then use new Long(x).
  • If T is float, then use new Float(x).
  • If T is double, then use new Double(x).

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

Now only reference values need to be considered:

  • If the reference is null, it is converted to the string "null" (four ASCII characters n, u, l, l).
  • Otherwise, the conversion is performed as if by an invocation of the toString method of the referenced object with no arguments; but if the result of invoking the toString method is null, then the string "null" is used instead.

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.

See §5.4 for details of the string conversion context.

15.18.1.

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.

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/


This java code:

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; 

into

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

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

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

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