摘要
日常使用java中,java.lang.String类几乎是使用最为频繁的一个类,此系列主要介绍String的具体实现以及作者对其进行了什么样的优化操作。
实现
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
private int hash;
private static final long serialVersionUID = -6849794470754667710L;
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0];
//其他函数
......
}
String的一些基本信息
1.String被final修饰符修饰,表示String是一个不可变类,一旦创建,就无法修改其中的内容。
2.实现了java.io.Serializable, Comparable<String>, CharSequence
三个接口
3.String中储存核心内容的数据结构是一个char数组。
String的不可变特性
前面说到String由final修饰,并且所有可能更改其核心存储内容的char[]数组的方法的返回值全都是返回一个新的字符串,保证了char[]无法被修改。
测试代码
public static void main(String[] args) {
String v="This is a String value!";
char[] c=new char[]{'a','s','d'};
change(v,c);
System.out.println(v);
System.out.println(c);
}
private static void change(String value,char c[]){
value="This is a New String value!";
c[0]='N';
}
为了对比,我们引入char数组
如果你认为输出是:
This is a String value!
Nsd
那你就忽略了String类的不可变特性。
首先,我们初始化了一个String和char[]变量,其指向的值分别为This is a String value!
和a``s``d
,调用change(String value,char c[])
方法时,将双方的地址传入方法。
最初,方法参数value指向传入的参数v,此时传入的参数v的地址指向This is a String value!
的地址,所以value指向的值为This is a String value!
。当重新向方法参数value赋值时,由于String的不可变性,方法参数value指向了新地址This is a New String value!
。char[]则直接改变了存在内存中的内容。函数调用完毕,继续执行下一步。
由于要输出v的值,此时v依然指向This is a String value!
的地址,c指向的也同样是一开始数组的地址,而方法体直接改变了地址中的值。
所以输出应该为
This is a String value!
Nsd
上图中可以了解到,栈区指向的地址不变,而只有char[]数组在内存中实际发生了改变。
String的声明方式
常用的两种方式
String s1="This is a String value!";
String s2=new String("This is a String value!");
那么这两种声明方式对java来说有什么不一样的地方呢?
测试代码
String value1="This is a String value!";
String value2="This is a String value!";
String value3=new String("This is a String value!");
System.out.println(value1==value2);
System.out.println(value1==value3);
System.out.println(value2==value3);
输出
true
false
false
上一节说到==
操作符比较的是两者引用的地址是否一致。
也就是说value1``value2
指向的是同一个地址
这是JVM对String的第一处优化。
具体细节,下节再讲。