关于 Java JDK 中内置的一个类:java.lang.String

关于 Java JDK 中内置的一个类:java.lang.String
1、String 表示字符串类型,属于引用数据类型,不属于基本数据类型。
2、在 java 中随便使用双引号括起来的都是 String 对象。例如:“abc”, “def”, “hello world!”,这是 3 个 String 对象。
3、java 中规定,双引号括起来的字符串,是不可变的,也就是说 “abc” 自出生到最终死亡,不可变,
不能变成 “abcd”,也不能变成 “abd”。
4、在JDK当中双引号括起来的字符串,例如:“abc”, “def” 都是直接存储在“方法区”的“字符串常量池”当中的。
为什么SUN公司把字符串存储在一个“字符串常量池”当中呢?
因为字符串在实际的开发中使用太频繁。为了执行效率,所以把字符串放到了方法区的字符串常量池当中。
注意:凡是双引号括起来的都在字符串常量池中有一份。

关于String类中的构造方法。
第一个:String s = new String(“”);
第二个:String s = “”; 最常用
第三个:String s = new String(char数组);
第四个:String s = new String(char数组 ,起始下标, 长度);
第五个:String s = new String(byte数组);
第六个:String s = new String(byte数组, 起始下标, 长度);

对于直接声明的字符串,形如:String x = “”; 则变量x直接指向常量池中;
对于new出来的字符串,new String(“”); 则存储于堆中,但存储的是指向常量池的引用;
intern方法可以向常量池存储字符串,并返回一个常量池的引用对象;
作者:单名一个冲
链接:https://www.jianshu.com/p/1fad17376b49
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
例:
@Test
public void test1(){
String str1 = new String(“This is String”);
String str2 = “This is String”;
System.out.println(str1 == str2); // false
System.out.println(str1.equals(str2)); // true
}

StringBuffer:
思考:我们在实际的开发中,如果需要进行字符串的频繁拼接,会有什么问题?
因为 java 中的字符串是不可变的,每一次拼接都会产生新字符串。
这样会占用大量的方法区内存。造成内存空间的浪费。
String s = “abc”;
s += “hello”;
就以上两行代码,就导致在方法区字符串常量池当中创建了3个对象:
“abc”
“hello”
“abchello”
String s = “”;
// 这样做会给 java 的方法区字符串常量池带来很大的压力。
for(int i = 0; i<100; i++){
// s += i;
s = s + i;
System.out.println(s);
}

如果以后需要进行大量字符串的拼接操作,建议使用JDK中自带的:
java.lang.StringBuffer
java.lang.StringBuilder
不建议使用 “+”连接字符串的方式,这样做会给java的方法区字符串常量池带来很大的压力。

byte 数组:
StringBuffer 底层实际上是一个 byte[] 数组。往 StringBuffer 中放字符串,实际上是放到 byte 数组当中了。
StringBuffer 的初始化容量是 16。

StringBuffer 不会产生新的对象,因为之前的对象都被垃圾回收器GC回收了。

如何优化StringBuffer的性能?
在创建StringBuffer的时候尽可能给定一个初始化容量。
最好减少底层数组的扩容次数。预估计一下,给一个大一些初始化容量。
关键点:给一个合适的初始化容量。可以提高程序的执行效率。

StringBuffer和StringBuilder的区别?
StringBuffer中的方法都有:synchronized关键字修饰。表示StringBuffer在多线程环境下运行是安全的。
StringBuilder中的方法都没有:sychronized关键字修饰,表示StringBuilder在多线程环境下运行是不安全的。

StringBuffer是线程安全的。
StringBuilder是非线程安全的。

1、String为啥是不可变的?
源代码,String 类中有一个 byte[] 数组,这个 byte[] 数组采用了 final 修饰,因为数组一旦创建长度不可变。
并且被 final 修饰的引用一旦指向某个对象之后,不可再指向其它对象,所以 String 是不可变的!
“abc” 无法变成 “abcd”
2、StringBuilder/StringBuffer 为什么是可变的呢?
源代码,StringBuffer/StringBuilder 内部实际上是一个 byte[] 数组,这个 byte[] 数组没有被 final 修饰,
StringBuffer/StringBuilder 的初始化容量是16,当存满之后会进行扩容,底层调用了数组拷贝的方法。
System.arraycopy() . . .是这样扩容的。所以 StringBuilder/StringBuffer 适合于使用字符串的频繁拼接操作。
3、字符串不可变是什么意思?是说双引号里面的字符串对象一旦创建不可变。
String s4 = “abc”;
s4 变量是可以指向其它对象的。字符串不可变是说以上变量 s4 不可变。说的是”abc“这个对象不可变。
s4 = “xyz”;
例:
public static void main(String[] args) {
String a = “hello”;
a = “hello hello”;
System.out.println(a); // hello hello
}