String类的一些理解
String类表示字符串。Java程序中的所有字符串例如"abc"都实现为此类的实例。
字符串是不变的,它的值创建无法更改
在字符串内部是使用char数组进行存储。因为数组一经确定,长度无法改变。所有说字符串一经确定之后是改变不了的。
例如: String str ="abc";
相当于: char data [] = {'a','b','c'};
String str = new String(data);
那么咋们以前拼接字符串是怎么做呢?拼接之后长度不是改变了吗?
如:
从上面可以看出,它已经改变了,其实是没变的,a还是a,b还是b,拼接后产生了是新对象c。
String对象是不可变的,所以共享他们
String text1 = "123123";
String text2 = "123123";
System.out.println(text1 == text2);
结果为true。
咋们知道两个不同对象,用”==“比较的是地址值,那为什么结果会是true呢?原因是java设计了这样一个想法,两个字符串如果内容完全相同,则采用同一块内存地址。
不过需要注意的是,如果是通过new产生的,那即使它们内容相同,地址也会是不同的
String拼接字符串的弊端
String text1 = "锄禾日当午";
String text1 = "汗滴禾下土";
String text1 = "床前明月光";
text1 = text1+text2+text3;
咋们来看上面字符串在栈跟堆的存储位置
当发生text1 = text1+text2+text3;
此时栈跟堆的变化为:
从上面可以看出,当执行完代码后0x123跟0x126地址因为没有引用,所以相当于内存垃圾了,而且存储在堆内存的永久代中,并不会被gc回收。
那就有一个值得思考的问题:咋们只用了两个加号,就产生了两个内存垃圾,那如果是很多个字符串相加呢,是不是就会产生很多垃圾内存,这样会导致内存占用过大,所以字符串拼接能避免就应该避免咯,特别是大量的拼接。
但有时候业务需要,就避免不了了,那该怎么办?
jdk提供了两个类,很好解决了这个问题:StringBuffer,StringBuilder
这两个类与String不用的点是,这两个类是可变字符序列,而String是定长字符序列。两个类的使用方式完全一致,区别就是一个线程安全,一个是线程不安全,这个点以后再分享。
用法如下:
//线程不安全的实现
StringBuilder sb = new StringBuilder();
//线程安全的实现
//StringBuffer sb = new StringBuffer();
sb.append("1");
sb.append("2");
sb.append("3");
String text = sb.toString();
System.out.println(text);