public class StringTest {
public static void main(String[] args) {
String a = “ab”;
System.out.println(”String a = “ab”;”);
String b = “cd”;
System.out.println(”String b = “cd”;”);
String c = “abcd”; String d = “ab” + “cd”;
if (d == c) {
System.out.println(”"ab”+”cd” 创建的对象 “加入了” 字符串池中”);
}
else {
System.out.println(”"ab”+”cd” 创建的对象 “没加入” 字符串池中”);
} String e = a + “cd”;
if (e == c) {
System.out.println(” a +”cd” 创建的对象 “加入了” 字符串池中”);
}
else {
System.out.println(” a +”cd” 创建的对象 “没加入” 字符串池中”);
}
}
}
为什么e和c指向的不是同一个对象??请高手做出解释,谢谢。。
public static void main(String[] args) {
String a = “ab”;
System.out.println(”String a = “ab”;”);
String b = “cd”;
System.out.println(”String b = “cd”;”);
String c = “abcd”; String d = “ab” + “cd”;
if (d == c) {
System.out.println(”"ab”+”cd” 创建的对象 “加入了” 字符串池中”);
}
else {
System.out.println(”"ab”+”cd” 创建的对象 “没加入” 字符串池中”);
} String e = a + “cd”;
if (e == c) {
System.out.println(” a +”cd” 创建的对象 “加入了” 字符串池中”);
}
else {
System.out.println(” a +”cd” 创建的对象 “没加入” 字符串池中”);
}
}
}
为什么e和c指向的不是同一个对象??请高手做出解释,谢谢。。
如果 String e = "ab" +"cd";那么就是一个对象了,
你这样不是
1.通过常量表达式计算的String,计算在编译时进行,并将它作为String字面常量对待。
2.通过连接操作得到的String(非常量表达式),连接操作是运行时进行的,会新创建对象,所以它们是不同的。
同理 String b = “cd”; String c = “abcd”; 都在数据空间分配了空间 “cd” 空间 “abcd”,而在栈内存中分配了空间b指向 “cd”,空间c指向“abcd”
语句 String d = “ab” + “cd”; 以为 “ab” + “cd” 是字符串相加,相当于“abcd”; 这个时候编译器有个优化,并没有在数据空间分配一个新的内存来存放“abcd”,以为它发现已经有个“abcd”存在,所以他把存在的“abcd”的地址赋值给在栈内存空间新分配的空间d,当做if (d == c)时,d和c里存放的都是数据空间中“abcd”的地址,所以d等于c,if判断成立
容器内我们再来看看 String e = a + “cd”; 语句编译器是如何编译的
首先一样 在栈内存空间中分配了一个新的空间 e ,而a + “cd”编译器编译时,a为一个引用(因为a为一个变量,这里引用了这个变量),在java中,所用的引用都会在堆内存空间中分配一个空间,所以此时在堆内存空间中开辟了一个空间,这个空间存放了a的值(就是数据空间中“ab”的地址)和数据空间中“cd”的地址,而此时在栈空间中e的值为a + “cd”在堆空间得地址,此时在做 if (e == c) e为a + “cd”在堆空间得地址, c为“abcd”在数据空间中的地址 结果明显是不相等的!
如果此时要得到if (e == c)为true,需要用到函数equalsif()方法。
同理 String b = “cd”; String c = “abcd”; 都在数据空间分配了空间 “cd” 空间 “abcd”,而在栈内存中分配了空间b指向 “cd”,空间c指向“abcd”
语句 String d = “ab” + “cd”; 因为 “ab” + “cd” 是字符串相加,相当于“abcd”; 这个时候编译器有个优化,并没有在数据空间分配一个新的内存空间来存放“abcd”,因为它发现已经有个“abcd”存在,所以它把存在的“abcd”的地址赋值给在栈内存空间新分配的空间d,当做if (d == c)时,d和c里存放的都是数据空间中“abcd”的地址,所以d等于c,if判断成立
让我们再来看看 String e = a + “cd”;语句,编译器是如何编译的
首先一样 在栈内存空间中分配了一个新的空间 e ,而a + “cd”编译器编译时,a为一个引用(因为a为一个变量,这里引用了这个变量),在java中,所用的引用都会在堆内存空间中分配一个空间,所以此时在堆内存空间中开辟了一个空间,这个空间存放了a的值(就是数据空间中“ab”的地址)和数据空间中“cd”的地址,而此时在栈空间中e的值为a + “cd”在堆空间得地址,此时在做 if (e == c) e为a + “cd”在堆空间得地址, c为“abcd”在数据空间中的地址结果明显是不相等的!
如果此时要得到if (e == c)为true,需要用到函数equals()方法。
后者的一个对象和一个字面常量相加发生在运行期,而且是StringBuilder.toString()的结果,这个对象放在栈里面了
a为一个引用(因为a为一个变量,这里引用了这个变量),在java中,所用的引用都会在堆内存空间中分配一个空间,所以此时在堆内存空间中开辟了一个空间,这个空间存放了a的值
不矛盾吗?
是e指向堆内存 应为是e引用了a,我说的是a为一个引用 并不是a指向堆内存
而此时在栈空间中e的值为a + “cd”在堆空间得地址 说明e指向这个新分配的内存空间 这个空间存放了a的值 说的是新开辟的内存空间存放了a的值,就是新开辟的内存空间指向数据空间中的“ab”,实际上在堆内存中的这个内存空间里有分割成两个空间,一个指向数据空间中的“ab”,另指向数据空间中的“cd”
String b = "cd";
String c = "abcd";
String d = "abcd";
String e = (new StringBuilder(String.valueOf(a))).append("cd").toString();这是我看到的。你觉得不爽可以自己写个智能编译器,把e 也解释成 "abcd" ,不过这可能和java规范有冲突。^^
// Home Page : http://members.fortunecity.com/neshkov/dj.html - Check often for new version!
// Decompiler options: packimports(3)
// Source File Name: Test.javaimport java.io.PrintStream;public class StringTest
{ public StringTest()
{
} public static void main(String args[])
{
String s = "ab";
System.out.println("String a = \"ab\";");
String s1 = "cd";
System.out.println("String b = \"cd\";");
String s2 = "abcd";
String s3 = "abcd";
if(s3 == s2)
System.out.println("\"ab\"+\"cd\" \u521B\u5EFA\u7684\u5BF9\u8C61 \"\u52A0\u5165\u4E86\" \u5B57\u7B26\u4E32\u6C60\u4E2D");
else
System.out.println("\"ab\"+\"cd\" \u521B\u5EFA\u7684\u5BF9\u8C61 \"\u6CA1\u52A0\u5165\" \u5B57\u7B26\u4E32\u6C60\u4E2D");
String s4 = (new StringBuilder()).append(s).append("cd").toString();
if(s4 == s2)
System.out.println(" a +\"cd\" \u521B\u5EFA\u7684\u5BF9\u8C61 \"\u52A0\u5165\u4E86\" \u5B57\u7B26\u4E32\u6C60\u4E2D");
else
System.out.println(" a +\"cd\" \u521B\u5EFA\u7684\u5BF9\u8C61 \"\u6CA1\u52A0\u5165\" \u5B57\u7B26\u4E32\u6C60\u4E2D");
}
}
我什么都不想说,贴出源代码大家都好看!