JAVA中字符串是不可改变的,(final char[]),这样编译器可以安排共享的字符串。如果拷贝一个字符串变量,两个串将共享相同的字符。
编译器和JVM一般会根据代码的实际情况来安排共享存储。
import java.util.Scanner;
public class stringisfinal {
static String stStr = "hello";
public static void main(String[] args){
String a = "hello";
String b = "hello";
String c = a;
String d = aStaticString();
String e = aInputString();
System.out.println(a == b);//true
System.out.println(a == "hello");//true
System.out.println(a == c);//true
System.out.println(c == b);//true
System.out.println(a == d);//true
System.out.println(a == e);//false
System.out.println(a == stStr);//true
System.out.println(a.substring(0, 4) == "hell");//false
System.out.println(a.substring(0, 5) == "hello");//true
}
public static String aStaticString(){
return "hello";
}
public static String aInputString(){
Scanner cin = new Scanner(System.in);
return cin.next();
}
}
可见,对于编译时能够确定的串(a,b,c,d,stStr,”hello”),而它们的值又是一样的,JVM把它们放在同一个位置来共享;
对于aInputString()返回的e,由于不确定,所以是临时创建的对象。
对于最后两个,可以先看看String的substring()方法的定义
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > count) {
throw new StringIndexOutOfBoundsException(endIndex);
}
if (beginIndex > endIndex) {
throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
}
return ((beginIndex == 0) && (endIndex == count)) ? this :
new String(offset + beginIndex, endIndex - beginIndex, value);
}
对于a.substring(0,4)虽然也是编译时在这个程序中是确定的,要求编译器编译时知道a.substring(0,4)的内容就是”hell”是要求过高了,而且也许不放在一起可能有更灵活的目的(我学得比较浅,就请读者指教了。)
而a.substring(0,5),由
return ((beginIndex == 0) && (endIndex == count)) ? this :
new String(offset + beginIndex, endIndex – beginIndex, value);
可以看出,子串长度刚好是原串本身的长度时,返回的是this,所以就不难解释前一个比较是false而这个是true了。
