(1)String为什么说是不可变的?
jdk源码中,String是final修饰的
那么就有必要说明一下final 这个关键字
1.final类不能被继承,没有子类,final类中的方法默认是final的。
2.final方法不能被子类的方法覆盖,但可以被继承。
3.final成员变量表示常量,只能被赋值一次,赋值后值不再改变。
注:用final修饰变量(即常量)时,该变量必须赋初始值,且只能被赋值一次,赋值后值不再改变(可以不用在声明时赋值,在构造里赋值;要么声明时赋值,要么构造时赋值)
String这个类的定义的final对象都在他的构造函数里赋值了。
public String() {
this.offset = 0;
this.count = 0;
this.value = new char[0];
}
/**
* Initializes a newly created {@code String} object so that it represents
* the same sequence of characters as the argument; in other words, the
* newly created string is a copy of the argument string. Unless an
* explicit copy of {@code original} is needed, use of this constructor is
* unnecessary since Strings are immutable.
*
* @param original
* A {@code String}
*/
public String(String original) {
int size = original.count;
char[] originalValue = original.value;
char[] v;
if (originalValue.length > size) {
// The array representing the String is bigger than the new
// String itself. Perhaps this constructor is being called
// in order to trim the baggage, so make a copy of the array.
int off = original.offset;
v = Arrays.copyOfRange(originalValue, off, off+size);
} else {
// The array representing the String is the same
// size as the String, so no point in making a copy.
v = originalValue;
}
this.offset = 0;
this.count = size;
this.value = v;
}
他的设计理念是先申明,而不赋初值,这中变量叫final空白,但是在使用空白final之前必须被初始化,在构造函数里赋值
final修饰的索引,对象不能改变,但是对象的内容可以改变。
例如:
final A a = new A();
a.value = 2;
这样是可以的,但是如果再从新赋值a就报错了:a = new A();
4.final不能用于修饰构造方法。
(2)String为什么不用new 可以直接赋值
java语法就这么规定的。
因为String类太常用了,这样直接赋值,避免多次创建内容相同的String对象,节省空间,提高效率。
Java运行环境有一个字符串池,由String类维护。执行语句String str="abc"时,首先查看字符串池中是否存在字符串"abc",如果存在则直接将"abc"赋给str,如果不存在则先在字符串池中新建一个字符串 "abc",然后再将其赋给str。执行语句String str=new String("abc")时,不管字符串池中是否存在字符串"abc",直接新建一个字符串"abc"(注意:新建的字符串"abc"不是在字符串池中),然后将其付给str。前一语句的效率高,后一语句的效率低,因为新建字符串占用内存空间。String str = new String()创建了一个空字符串,与String str=new String("")相同。