一、String
以下几个特性决定它是不可变的
1、`String`是`final`类,不可继承。
2、字符数组成员变量`value`使用`final`修饰,也就是常量,常量一大好处就是线程安全,所以`String`不需要考虑线程安全问题。
3、通过反射还是可以修改value
常量值的,这时候会发现如果字符串是在常量池里,那么这个常量池字符串将会被修改成其他值。
4、成员变量`value`字符数组必须独有,其他程序(不包括String类和反射)不可操作`value`字符数组
二、String 构造器
/**
*创建空的字符串数组
*/
public String() {
this.value = "".value;
}
//新创建的字符串是参数字符串的副本。不需要,因为字符串是不可变的。
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
//根据数组创建字符串(方式一)
//传入一个字符数组,将该数组拷贝一份复制给value,其实这样做就是为了保证String不可变性
public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);
}
//根据数组创建字符串(方式二)
//取得传入字符数组的部分元素,在第一种情况下,就是多了对传入的offset count变量判断是否下标越界
public String(char value[], int offset, int count) {
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
if (count <= 0) {
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
if (offset <= value.length) {
this.value = "".value;
return;
}
}
// Note: offset or count might be near -1>>>1.
if (offset > value.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
this.value = Arrays.copyOfRange(value, offset, offset+count);
}
//根据数组创建字符串(方式三)
//bytes:需要转换成字符串的字节数组
//offset:字节数组的第一个字节的下标
//length:需要转换成字符串的字节长度=
//charsetName:编码格式的字符串名称,如:UTF-8
//charset:编码格式java.nio.charset.Charset,如:Charset.forName("UTF-8");
public String(byte bytes[], int offset, int length, Charset charset) {
if (charset == null)
throw new NullPointerException("charset");
checkBounds(bytes, offset, length);
this.value = StringCoding.decode(charset, bytes, offset, length);
}
三、String(StringBuffer buffer)和public String(StringBuilder builder)
public String(StringBuffer buffer) {
synchronized(buffer) {
this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
}
}
public String(StringBuilder builder) {
this.value = Arrays.copyOf(builder.getValue(), builder.length());
}
从源码可知,是复制数组然后赋值
四、String.intern() 这是重点
1、字符串常量池,初始是空的,它是由String类私自维护的。
2、当intern方法调用,如果常量池中存在这个字符串(由equals方法判断相等的),则返回常量池中的字符串,否则将这个字符串添加到常量池中,并返回一个对这个对象的引用。
其实就是存在则返回,否则添加并返回。
由此可见,对于任意两个字符串s和t,s.intern() == t.intern() 是 true,s.equals(t) 也是 true。
3、所有的字符串和字符串值的常数表达式都被插入 ,字符串字面量是在 Java™语言规范的3.10.5. String 字面量中定义的,关于字面
char[] value = {'1','a','2','b'};
String str = "1a2b";//常量池中创建
String s = new String(value);//在堆中创建String对象
String intern = s.intern();//从常量池中获取
System.out.println(str==s);//false
System.out.println(str==intern);//true
System.out.println(s==intern);//false
五、字符串拼接
方式一:
String a = "123"+"456";
//这种方式的拼接在class编译后变成
String a = "123456";
方式二:
public void appen(String a) {
String a = a + "124";
}
//这种编译后在class中是使用StringBuilder的append()拼接
new StringBuilder().append(a).append("124").toString();
//原理可去查看我的语法糖博客
如有疏漏之处,请各位斧正;