黑马程序员技术交流社区

标题: 关于字符串的奇怪问题 [打印本页]

作者: 陈磊    时间: 2011-8-3 22:09
标题: 关于字符串的奇怪问题
[code=java]class Other {
        static String hello = "Hello";
}

public class HelloWorld {
        public static void main(String[] args) {
                String hello = "Hello", lo = "lo";

                System.out.println((hello == "Hello") + " ");
                System.out.println((Other.hello == hello) + " ");
                System.out.println((Other.hello == hello) + " ");
                System.out.println((hello == ("Hel" + "lo")) + " ");
                System.out.println((hello == ("Hel" + lo)) + " ");
                System.out.println(hello == ("Hel" + lo).intern());
        }
}[/code]我想问的是 System.out.print((hello == ("Hel"+lo)) + " "); 这一行的结果为什么是false??
想半天想不明白
作者: 匿名    时间: 2011-8-3 22:18
hello是一个String对象,在内存栈中存放了一个地址引用,实际的“Hello”放在内存堆中,而你的“Hel”+lo
是Hel这个字符串对象加上lo这个字符串对象,后者是两个String对象,在内存栈中有两个引用,在堆中有两个实际的数据存储,前者是一个对象,后者是两个对象,用==比较当然是folse啦
作者: 覃俊瑞    时间: 2011-8-3 23:06
楼上的童鞋,比较的是一个对象,不是两个对象!我查了不少资料,所以说呢,现在我对String还是比较了解的。

hello 发生在编译时,被放在字符串池String pool中,栈内存里,也就是说,hello在编译时已经知道它的值是"hello"了
"Hel" + lo 发生在运行时,新生成的一个字符串,编译时,"Hel" + lo的值还不知道,因为这个表达式有引用参加运算,算是动态的字符串,只有在运行时才产生它的对象,这时才知道它的真正地址。你想想运行时产生的地址和编译时产生的地址会相同吗?

下面是字符串intern方法的api解释和其源码,看懂了你就知道方法返回的是字符串在字符串池的栈内存的引用。
而同一时间,字面值相同的字符串在字符串池中只有一个栈内存地址的引用,因为如果相同的字符串想加入到字符串池的时候,返回的是字符串池里面那个字面值相同的字符串的内存地址。所以"hello"==hello,("hel"+lo).intern()==hello,返回的都是true。[code=java]/* <p>
     * When the intern method is invoked, if the pool already contains a
     * string equal to this <code>String</code> object as determined by
     * the {@link #equals(Object)} method, then the string from the pool is
     * returned. Otherwise, this <code>String</code> object is added to the
     * pool and a reference to this <code>String</code> object is returned.
     * <p>
* @return  a string that has the same contents as this string, but is
     *          guaranteed to be from a pool of unique strings.
     */

public native String intern();[/code]我在帖子http://bbs.itheima.com/thread-377-1-1.html中有较详细的回答,你可以参考。
[ 本帖最后由 覃俊瑞 于 2011-08-03  23:08 编辑 ]
作者: 匿名    时间: 2011-8-3 23:15
首先  看着你定义的那些变量 我脑袋大了:L
==符号是判断两个对象句柄是否相等(也就是两个句柄是否指向同一个对象)
hello 是指向常量池中的"Hello" 的引用
从下面的一行[code=java] System.out.println(hello == ("Hel" + lo).intern());[/code]可以判断他们为false的原因是"Hel" + lo运算后的Hello不在常量池中。
"Hel" + lo返回的是一个指向值为"Hello"的StringBuffer对象的引用。
所以两个引用不等。false
这是我自己的理解!仅供参考……
作者: 匿名    时间: 2011-8-3 23:28
:loveliness: admin老师您过奖啦,我不过是多百度一下。
作者: 匿名    时间: 2011-8-4 12:27
不是说打印的时候 会有个自动toString么 是不是因为 这个 “hel” +lo 字符串加引用 没法 toString 了
作者: 覃俊瑞    时间: 2011-8-5 19:26
标题: 回复 地板 的帖子
System.out.println(("Hel" + lo).toString());//Hello

“hel” +lo -----运行时,会创建一个新的字符串对象,再返回一个地址的引用,当打印这个引用的时候,该引用会调用父类String的toString()方法。
作者: 冯龙辉    时间: 2011-8-6 13:10
标题: 回复 楼主 的帖子
:handshake 原因:String类型是不可变的。
解析:hello和lo是两个不同的对象,(“Hel”+lo)是新创建的字符串类型对象,
这里的三个对象是不同的,hello == ("Hel"+lo)   当然要false了。
[ 本帖最后由 fenglh 于 2011-08-06  13:17 编辑 ]




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2