1,对String直接量,Java会使用一个字符串池来保存,因此new String(“java”)实际上创建了两个对象:在堆内存中的String类型的对象和在栈内存中的字符串直接量对象。并且,如果字符串使用连接字符串的方式创建,如果字符串在编译时(即不包含任何变量)即可确定,则将其指向字符串池中的对应对象。
2,通过字符串常量拼接的方式实现的字符串实际上只保存最后计算结果到字符串池,而不会创建中间结果的字符串池对象。即:String s=”ja”+”va”;实际上只创建了一个字符串直接量,而不是3个。
3,对于String对象的比较,有这样的含义: ==比较的实际上是内存地址,而equals比较的才是内存地址中对应的值。并且equals底层实际上是通过字符序列的compareTo实现的。
代码如下所示:
public static void main(String[] args) {
// TODO Auto-generated method stub
String s1 = new String("java");// 该语句实际创建了两个对象,
//一个是堆内存中包含值“java”的String对象,一个是栈内存中的值为“java”的String对象
//并且s1实际指向的是堆内存中的String对象
String s2 = "java";//只创建了一个String直接量,直接指向字符串池中已存在的String对象。
String s3 = "java";
System.out.println("通过==比较new对象与字符串直接量的值" + (s1 == s2));//==比较的实际是内存地址
System.out.println("通过equals比较new对象与字符串直接量的值" + s1.equals(s2));//equals比较的才是值
System.out.println("通过==比较字符串直接量的值" + (s2 == s3));
System.out.println("通过equals比较new对象与字符串直接量的值" + s2.equals(s3));
String s4="ja"+"va";//连接字符串中不包含变量,可以在编译时就确定,因此指向字符串池中的对象
System.out.println("字符串连接(不包含变量)::通过==比较字符串直接量的值" + (s4 == s3));
System.out.println("字符串连接(不包含变量)::通过equals比较new对象与字符串直接量的值" + s4.equals(s3));
String temp="ja";
String s5=temp+"va";//虽然它的值域s4相同,但指向的是堆内存中的String对象
System.out.println("字符串连接(包含变量)::通过==比较字符串直接量的值" + (s5 == s3));
System.out.println("字符串连接(包含变量)::通过equals比较new对象与字符串直接量的值" + s5.equals(s3));
final String temp1="ja";
String s6=temp1+"va";//final类型的是常量,编译时可以确定,因此指向的是栈内存中的String对象
System.out.println("字符串连接(包含final常量)::通过==比较字符串直接量的值" + (s6 == s3));
System.out.println("字符串连接(包含final常量)::通过equals比较new对象与字符串直接量的值" + s6.equals(s3));
System.out.println();
System.out.println("通过identityHashCode确定字符串直接量的存在");
System.out.println("s1的Hashcode"+System.identityHashCode(s1));
System.out.println("s2的Hashcode"+System.identityHashCode(s2));
System.out.println("s3的Hashcode"+System.identityHashCode(s3));
System.out.println("s4的Hashcode"+System.identityHashCode(s4));
System.out.println("s5的Hashcode"+System.identityHashCode(s5));
System.out.println("s6的Hashcode"+System.identityHashCode(s6));
}