java字符串常量问题
网上看到的一篇文章讲的字符串常量。其它没什么问题,主要是
str7 == str8 的值为false,表示这个不理解,还望达人们能指点一下。如果能从引用(or地址?)的创建、改变的角度谈谈则再好不过了。
先行谢过~
代码如下(代码已经被我简化过了,只保留有疑问部分):
public class DemoStringCreation {
public static void main(String args[]) {
String s = "lo";
String str7 = "Hel" + s;
String str8 = "He" + "llo";
System.out.println(" str7 == str8 is " + (str7 == str8));
System.out.println(" str7.equals(str8) is " + str7.equals(str8));
}
}
/******************************* updated 2014.04.18 14:40 ********************/
@brayden
大大从编译的角度给出了解释,我相信这个解释足够底层、根本,无奈我看不太明白
-_-!!
这篇文章
最下面几段给了解释,理解起来似乎有了些感觉。示例代码与相应的解释我也贴一下,
/****************粘贴开始******************/
String a = "ab";
String bb = "b";
String b = "a" + bb;
System.out.println((a == b)); //result = false
分析:JVM对于字符串引用,由于在字符串的"+"连接中,有字符串引用存在,而引用的值在程序编译期是无法确定的,即"a" + bb无法被编译器优化,只有在程序运行期来动态分配并将连接后的新地址赋给b。所以上面程序的结果也就为false。
String a = "ab";
final String bb = "b";
String b = "a" + bb;
System.out.println((a == b)); //result = true
分析:和上面例子唯一不同的是bb字符串加了final修饰,对于final修饰的变量,它在编译时被解析为常量值的一个本地拷贝存储到自己的常量 池中或嵌入到它的字节码流中。所以此时的"a" + bb和"a" + "b"效果是一样的。故上面程序的结果为true。
String a = "ab";
final String bb = getBB();
String b = "a" + bb;
System.out.println((a == b)); //result = false
private static String getBB() {
return "b";
}
分析:JVM对于字符串引用bb,它的值在编译期无法确定,只有在程序运行期调用方法后,将方法的返回值和"a"来动态连接并分配地址为b,故上面 程序的结果为false。
/****************粘贴结束******************/
Ok,这里我的新问题又来了,什么时候是编译期,什么时候是才算是运行期呢?(问题是不是太基础了?我自己都怀疑……装载、编译、运行这些概念是经常碰到,就是从来没有完全弄清楚过程)如果这个问题解决了,那按照上面贴的这篇文章里的解释,就能完全理解通了。或者,能不能把@brayden大大的那个编译解释明白一点点?
Answers
==是比较两个字符串引用的地址是否相同,即是否指向同一个对象,而equals方法则比较字符串的内容是否相同。
例如String a = "abc";
String b = "abc";
a == b返回true,a.equals(b)同样返回true,这是为什么呢?
原来程序在运行时有一个字符串池,创建字符串时会先查找池中是否有相应的字符串,如果已经存在的话只需把引用指向它即可,如果没有则新建一个。
上例中创建a时,会在字符串池中首先创建一个"abc",然后a指向它;创建b时,由于"abc"已经存在,b直接指向它即可。
若改为:String a = "abc";
String b = new String("abc");
则a == b返回false,a.equals(b)返回true。因为创建b时不管"abc"是否存在都会new一个新的"abc",从而a和b指向的字符创对象是不同的,因此返回false。