Java 深究字符串String类(1)之运算符"+"重载

本文深入探讨Java中String对象的不可变性特点,分析String拼接时的性能问题,并提出使用StringBuilder进行优化的方法。

一.不可改变String

String对象是不可改变的,
查看JDK文档,发现String类中每一个看似修改String的方法,实际上都创建了一个新的String对象,而最初的String对象则丝毫未动.

java传递参数的时候,传递的是引用的一个拷贝,调用时,都会复制一份引用,而引用所指向的对象,一直呆在某一单一物理位置,从未变动过.

二.重载 “+” 与 StringBuilder

String对象是不可改变的,你可以给一个String对象加任意多的别名.
String对象是只读的,所要指向它的任何引用都不可能改变它的值.so不会对其他引用产生什么卵影响.
用于String类中的”+” / “+=” 是Java中仅有的两个重载过的操作符,而java并不允许我们重载任何操作符;

public class one {
    public static void main(String[] args) {
        String a = "abc";
        String b = "123" + a + "def" + 777;
        System.out.println(b);
    }
}

如上代码,可能这样工作:
String有append方法,然后返回一个新的String对象的引用,以包含连接后的字符串,然后再append , 再创建新对象.
这种方式当然行得通,但是为了生成最终的String,次方式会产生一堆需要垃圾回收的中间对象.然后发现其性能略lowBi.那么编译器真的会这样做吗?

来来~~,反编译生成的.class

javap -c one.class
这是JDK自带的工具 javap -c参数生成字节码

这里写图片描述

懂点汇编就行,,dup,invokevirtural 就是jvm上的汇编.

看好了:
6: dup
7: invokespecial #4 // Method java/lang/StringBuilder.””:()V
10: ldc #5 // String 123
12: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;


编译器自动引用java.lang.StringBuilder类,用以构造最终的String,为每个”+”调用一次append方法,最后调用toString方法生成最终的String并保存

三.what if 在循环里使用”+”呢

经过实验发现:

1.这样写:

String str = "";
for(int i = 0; i < num; i++)
{
    str += "a";
}

javap -c

这里写图片描述

5~33是循环体, 15句创建一个StringBuilder对象

可知StringBuilder在循环体内构建,每次循环,创建新的StringBuilder

2.这样写:

 StringBuilder a = new StringBuilder();
for(int i = 0; i < 10; i++)
{
    a.append(i); //只有String能"+"
}

这里写图片描述
只创建一个StringBuilder类

所以以后写的时候就知道咋回事了.

小明在学习C++面向对象程序设计之前,已经学习过C语言了。C语言中,字符串都是存储在字符数组中的,并在字符数组中存储一个特殊的字符'\0'作为字符串结束标志。并且在C语言中已经掌握了字符串相关处理等操作的函数,如字符串连接、比较等。今天的课堂上,C++老师Frank讲了运算符重载,刚好小明设计好了字符串STRING,想重载算术运算符+实现字符串连接功能,将第二个字符串连接到第一个字符串的后面,请你替小明完成这件事,并以的友元函数实现。 其中系统实现的字符串输入运算符(>>)可以输入长度不超过80的字符串,允许包含空格,允许是一个空串。 接口定义: class STRING{ char* pstr; public: STRING(const char* s="");//已实现 ~STRING();//已实现 STRING(const STRING& s);//已实现 STRING& operator=(const STRING& s); //已实现 friend STRING& operator+(STRING& s1, const STRING& s2); //将s2连接到s1后面,返回s1 friend istream& operator>>(istream& in, STRING& s); //已实现 friend ostream& operator<<(ostream& os, const STRING& s); //已实现 }; 评判程序样例: #include <iostream> #include <cstdio> #include <cstring> using namespace std; class STRING{ char* pstr; public: STRING(const char* s="");//已实现 ~STRING();//已实现 STRING(const STRING& s);//已实现 STRING& operator=(const STRING& s); //已实现 STRING& operator+(const STRING& s); //将s连接到当前字符串后面 friend istream& operator>>(istream& in, STRING& s); //已实现 friend ostream& operator<<(ostream& os, const STRING& s); //已实现 }; int main() { STRING s1, s2, s3, ss; cin >> s1 >> s2 >> s3; ss = operator+(s1, s2); //显式调用 cout << ss << endl; ss = s1 + s2; //隐式调用 cout << ss << endl; return 0; } /* 请在这里填写答案,你只需要实现算术运算符(+)重载即可 */ 输入样例: 每行输入一个字符串,可以含空格,可以为空串,长度不超过80个字符。例如: I Love C++ 输出样例: ILove ILoveC++ 代码长度限制 16 KB 时间限制 400 ms 内存限制 64 M
最新发布
06-04
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值