Java String类笔记
声明
文章均为本人技术笔记,转载请注明出处https://segmentfault.com/u/yzwall
String的不可变性
String的不可变性
// String declaration
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
...
}
public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);
}
-
String类字符串存储方式:值使用
final char value[]
类型的字符数组存储,因此一旦赋值不可改变;String类存储字符串,使用Array.copyof方法
value[]
赋值,并开辟内存空间;
String类不可继承:使用
final
修饰符,表示String类不可继承;String类提供的所有方法中,有返回String的一律新建一个String对象,防止对原String对象进行修改;
String对象创建
字符串常量池:位于常量池中,由String类私有维护,池中元素都是String对象,每个String对象的字面值是唯一的,由GC回收;
String常量对象创建场合:当String对象第一次常量赋值和调用String对象调用intern()
方法时,常量池中创建对应String常量对象;
String str1 = "abc";
String str2 = "abc";
String str3 = str1;
String str4 = new String("abcd");
String str5 = new String("abc");
String对象创建,分为直接常量赋值与new运算符创建,创建String新对象时创建1个或2个String对象;
直接字符串常量赋值
创建对象时,在编译阶段,编译器先去字符串常量池检查是否有String常量对象拥有字面值"abc",
存在/str2:在栈中创建引用,指向常量池中的Strng常量对象(字面值为"abc");
不存在/str1:在常量池中创建匿名Strng对象(字面值为"abc"),在栈中创建引用,指向String常量对象;
使用new运算符创建
创建对象时,程序先去字符串常量池检查是否有String对象拥有字面值"abc",
存在/str5:在栈中创建对象引用,在堆区为实例分配内存,但是字符数组value字段保存常量对象(常量池中)的value字段的引用;
不存在/str4:在栈中创建对象引用,在堆区为实例分配内存,在常量池中创建String常量对象,字符数组value字段保存常量对象(常量池中)的value字段的引用;
String类的intern()方法
String str6 = new String("abc");
String a = str6.intern();
String str7 = "xyz";
String b = str7.intern();
str.intern()
首先检查常量池中的String常量对象字面值是否有与str.value相等的,若有直接返回对应String常量对象的引用,否则在常量池中创建字面值为str.value的String常量对象并返回引用;
String类判等:equals方法和等号运算符:
String str1 = "abc";
String str2 = str1;
String str3 = new String("abc");
String str4 = str3;
String str5 = new String("abc");
// String equals只用于判断字面值是否相同,以下结果均为true
System.out.println(str1.equals(str2));
System.out.println(str1.equals(str3));
System.out.println(str3.equals(str4));
System.out.println(str3.equals(str5));
// false,str1与str3引用不同对象
System.out.println(str1 == str3);
// false,str3与str5引用不同对象
System.out.println(str3 == str5;
equals()
方法检测两个字符串变量/常量是否相等;==
运算符判断两个String对象的引用地址是否相同,即判断引用变量引用指向同一个对象;
String:空串与null
空串
""
是长度为0的字符串,用if(str.length() == 0)
或if(str.equals(""))
判断;null
表示String对象为空,用if(str == null)
判断;
String、StringBuilder,StringBuffer辨析
三者可变性与线程安全辨析
String类由于对象不可变,线程安全 【异】
StringBuilder与StringBuffer都继承AbstractStringBuilder类,字面值
char[] value
均可变【同】;StringBuffer中主要方法用
synchronized
加了同步锁,因此线程安全【异】;StringBuilder方法没有加同步锁,因此线程不安全,但在非多线程场景下,效率高于StringBuilder【异】;
三者适用场景【异】:
使用String类:适用于字符串不频繁变化的场景,比如常量生命,少量变量运算;
使用StringBuilder类:适用于单线程环境下字符串频繁变化的场景;
使用StringBuffer类:适用于多线程环境下字符串频繁变化的场景;
String类重写了equals()方法和hashCode()方法,StringBuilder和StrngBuffer没有,因此将后两者对象存储Java集合类中会出现问题;
String对象"+/+="本质
在进行连接操作(“+”和 “+=”)时,String每次返回一个新的String实例,而StringBuffer/StringBuilder的
append()
直接返回this;String类“+”和 “+=”操作符是Java中唯一重载的两个操作符。这两个操作符都是编译器默认引入了StringBuilder类,最后都调用
toString()
方法返回String对象,StringBuilder临时对象被GC回收,因此效率极为低下;
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。