Java String类如何重写+;操作人员
为什么在Java中,当字符串是一个类时,您可以使用+运算符添加字符串?在Java String类如何重写+;操作人员,java,string,object,Java,String,Object,为什么在Java中,当字符串是一个类时,您可以使用+运算符添加字符串?在String.java代码中,我没有找到此运算符的任何实现。这个概念违反了面向对象吗?这是Java编译器的特性,它检查+运算符的操作数。并根据操作数生成字节码: 对于String,它生成concat字符串的代码 对于数字,它生成代码来添加数字 这是Java规范所说的: 运算符+和-称为加法运算符。 加法表达式: 乘法表达式 加法表达式+乘法表达式 加法表达式-乘法表达式 加法运算符具有相同的优先级,并且在语法上是相同的
String.java
代码中,我没有找到此运算符的任何实现。这个概念违反了面向对象吗?这是Java编译器的特性,它检查+
运算符的操作数。并根据操作数生成字节码:
- 对于String,它生成concat字符串的代码
- 对于数字,它生成代码来添加数字
-
称为加法运算符。
加法表达式:
乘法表达式
加法表达式+乘法表达式
加法表达式-乘法表达式
加法运算符具有相同的优先级,并且在语法上是相同的
左关联(它们从左到右分组)。如果其中一种类型
+
运算符的操作数为字符串
,则该操作为字符串串联
否则,+
运算符的每个操作数的类型必须是
可转换为原始数字类型(§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();