一、String
(一)、创建 String 对象
String str1 = new String("Hello World!"); //方法一
String str2 = "Hello World!"; //方法二
......
(二)、两种方法的坑
代码
String str1 = new String("Hello World!");
String str2 = "Hello World!";
if (str1 == str2) {
System.out.println("str1 == str2");
} else {
System.out.println("str1 != str2");
}
String str3 = "Hello World!";
if (str2 == str3) {
System.out.println("str2 == str3");
} else {
System.out.println("str2 != str3");
}
输出
str1 != str2
str2 == str3
原因
两个语句都是返回一个String对象的引用, 但JVM处理的方式不一样.
方法一: JVM 马上在堆区中创建String对象, 然后将对象的引用返回.(并不会添加至 String Pool 中, 除非显示的调用 String的intern方法)
方法二: JVM 首先在 String Pool 中通过String的 equals 方法查找对象池中是否有该String对象. 如果有,则直接返回而不会再重新创建; 如果没有, JVM 则在堆区中创建新的String对象, 将其引用返回, 同时将该引用添加至String Pool中.
String Pool不是在堆区,也不是在栈区,而是存在于方法区(Method Area)
(三)、常用的一些方法
String str = new String("Hello World!");
System.out.println(str.length());
System.out.println(str.substring(0, 5));
System.out.println(str.charAt(0));
System.out.println(str.equals("Hello World!"));
System.out.println(str.compareTo("Hello World!"));
System.out.println(str.replaceAll("o", "O"));
System.out.println(str.toLowerCase());
System.out.println(str.hashCode());
System.out.println(str.concat("Hahahaha!"));
(四)、hashCode 的实现
根据以下公式计算:
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
(s[i] 是字符串的第 i 个字符,n 是字符串的长度,^ 表示求幂。空字符串的哈希值为 0)
(五)、不可变对象
String 对象是不可变对象, 创建后就不可修改.
优势
- 安全(
String Pool/多线程) - 效率
二、StringBuffer
(一)、使用
StringBuffer stringBuffer = new StringBuffer("Hello");
System.out.println(stringBuffer);
stringBuffer.append("world!");
System.out.println(stringBuffer);
stringBuffer.reverse();
System.out.println(stringBuffer);
stringBuffer.delete(0, 1);
System.out.println(stringBuffer);
stringBuffer.reverse();
stringBuffer.insert(5, " ");
System.out.println(stringBuffer);
stringBuffer.replace(5, 11, "OOO");
System.out.println(stringBuffer);
stringBuffer.trimToSize();
Hello
Helloworld!
!dlrowolleH
dlrowolleH
Hello world
HelloOOO
(二)、错误的初始化方式
StringBuffer s = “abc”; //赋值类型不匹配
StringBuffer s = (StringBuffer)”abc”; //不存在继承关系,无法进行强转
(三)、与String对象之间的互转
String s = "abc";
StringBuffer sb1 = new StringBuffer("123");
StringBuffer sb2 = new StringBuffer(s); //String转换为StringBuffer
String s1 = sb1.toString(); //StringBuffer转换为String
三、StringBuilder
使用
StringBuilder sbuilder = new StringBuilder();
......
四、三角关系
(一)、关系图

(二)、区别
-
String继承于CharSequence,也就是说String也是CharSequence类型 -
StringBuilder和StringBuffer都是可变的字符序列。它们都继承于AbstractStringBuilder,实现了CharSequence接口 -
String是不可变的,StringBuffer、StringBuilder是可变的 -
StringBuilder是非线程安全的,而String(不可变对象)、StringBuffer(对方法加了同步锁或者对调用的方法加了同步锁)是线程安全的 -
StringBuilder适用于单线程环境,StringBuffer适用于多个线程操作同一个字符串 -
大部分情况下:
StringBuilder>StringBuffer>String
五、参考
Weafung原创。Weafung's Homepage | Weafung's Blog
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。