A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 丁二跃 中级黑马   /  2012-6-21 10:04  /  3241 人查看  /  14 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 丁二跃 于 2012-6-21 18:28 编辑

百度了一下,但是答案各不相同,不知道那个正确,求助

说法1:7个,a b c d ab abc abcd
说法2:1个 abcd String 的内部结构是通过StringBuilder实现的! 所以没有生成ab abc 等对象

纠结,哪种说法是正确的呢?还有对于第二种,这些常量字符串 a b c d 不算作对象吗?

评分

参与人数 1技术分 +1 收起 理由
黄奕豪 + 1 新手,鼓励一下!

查看全部评分

14 个回复

倒序浏览
本帖最后由 王明明 于 2012-6-21 10:11 编辑

String s = "a" + "b" + "c" + "d";
System.out.println(s == "abcd");
最终打印的结果应该为true。
在编译时去掉其中的加号,直接将其编译成一个这些常量相连的结果。第一行代码被编译器在编译时优化后,相当于直接定义了一个”abcd”的字符串
我觉得是建立了一个对象

回复 使用道具 举报


就创建了一个
String s = "a" + "b" + "c" + "d" + "e";
赋值符号右边的"a"、"b"、"c"、"d"、"e"都是常量
对于常量,编译时就直接存储它们的字面值而不是它们的引用


String s1 = "a";
String s2 = s1 + "b";
String s3 = "a" + "b";
System.out.println(s2 == "ab");
System.out.println(s3 == "ab");

     第一条语句打印的结果为false,第二条语句打印的结果为true,这说明javac 编译可以对
字符串常量直接相加的表达式进行优化,不必要等到运行期去进行加法运算处理,而是在编
译时去掉其中的加号,直接将其编译成一个这些常量相连的结果。
题目中的第一行代码被编译器在编译时优化后,相当于直接定义了一个”abcd”的字符串,

     所以,上面的代码应该只创建了一个String对象。写如下两行代码,
String s = "a" + "b" + "c" + "d";
System.out.println(s == "abcd");
最终打印的结果应该为true。
回复 使用道具 举报
本帖最后由 黑马—陈磊 于 2012-6-21 10:32 编辑

只创建了一个对象,"a"、"b"、"c"、"d"、"e"是常量 ,他们在编译时就会直接存储它们的值而不是它们的引用
在编译时就直接讲它们连接的结果提取出来变成了"abcde"
该语句在class文件中就相当于String s = "abcde"
然后当JVM执行到这一句的时候, 就在String pool里找
如果没有这个字符串,就会产生一个
回复 使用道具 举报
一共只创建了三个对象,而且最终只有一个,那就是“abcd”
因为向,单独的字符常量 'a' 'b' 'c' 'd' 在数据池,是静态的不需要创建,直接拿来就用:但是
请注意: 当 "a "+ "b" 时会创建一个对象“ab”,接着,“ab”+"c"又回创建 “abc”,然后呢,“abc”+"d"会最终创建"abcd",而之前创建的匿名字符创
“abc” "ab",由于失去引用,会最终被java垃圾回收期回收!值剩下 “abcd” 这一个,中途一共创建了,三个对象

回复 使用道具 举报
说法二太扯了,看过那么多关于String的资料都没看过这么扯的,String类的对象很特殊,既可以存在于编译时,也可以存在于运行时。
编译:String s="1";  "1"这个字符串对象就存在于常量池中,
运行:String s=new Strin("1");   存在于堆中。
说法一的是否正确我也不知道,只知道String s="a"+"b“ 是在常量池中产生3个对象,至于连加的就不清楚了。不知道5个还是7个。
回复 使用道具 举报
只创建一个String s 对象。
因为字符"a""b"...都为字符常量。jvm不需要为其创建新的对象。
回复 使用道具 举报
李元峰 发表于 2012-6-21 10:17
一共只创建了三个对象,而且最终只有一个,那就是“abcd”
因为向,单独的字符常量 'a' 'b' 'c' 'd' 在数据 ...

楼主,我刚验证了下,楼上几位都是对的,我说错了,只创建了一个对象
回复 使用道具 举报
孙峰 黑马帝 2012-6-21 10:38:26
9#
本帖最后由 孙峰 于 2012-6-21 10:40 编辑

围观吧
回复 使用道具 举报
String s1 = "a";
String s2 = s1 + "b";
天雷滚滚。。  

对于编译器而言,执行到String s2 = s1 + "b";  这段话时,只是在判断语法:左边是Strng类型引用,右边是String类型引用对象+String实例对象。OK语法通过,编译通过。跟上面那句话没有任何关系,基础加强有篇已经说的很清楚:请不要用运行时的思想去套在编译时的处理上。

System.out.println(s2 == "ab");  这段话只所以是false,是因为s2这个引用所指向的对象直到运行时才直到,也就是说一个引用+一个常量池中的对象的操作是在运行时,在堆中创建一个"ab"对象,然后赋给s2。 而"ab"这个对象在编译时就会在常量池中创建,当然是false

System.out.println(s3 == "ab");  s3也是引用,与s2的区别是:String s3 = "a" + "b";  这段话在编译时就创建了3个对象,s3指向的池后果的"ab"对象,
而s3=="ab"  右边的"ab"就是池的那个"ab"。

楼上的兄弟是怎么测试到池中有多少对象,求教!

回复 使用道具 举报
同上 楼主怎么验证的。求教;
回复 使用道具 举报
李元峰 发表于 2012-6-21 10:23
楼主,我刚验证了下,楼上几位都是对的,我说错了,只创建了一个对象

你是怎么验证的;分享下;
回复 使用道具 举报
邓杰 发表于 2012-6-21 12:32
你是怎么验证的;分享下;

package com.heima.test;

public class StringTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        String a="a";
        String b="b";
        String c="ab";
        String ab=a+b;//请注意这里
        System.out.println(c==ab);//得到的是false
        
        
        //但是请看下面的:
        String str1="ab";
        String str2="a"+"b";
        
        System.out.println(str1==str2);//得到的却是true,为什么,因为str1,和str2都是引用的字符串常量
        //再看下面的
        
        str2=str1+"c";//注意str1的值为 “ab"
        
        System.out.println(str2=="abc");//现在又是false,说明了只要虽然str1是指向字符串常量,但是现在str1已经是一个对象了,他参与运算的之后已经不是一个字符串常量而是到了堆内存,要不怎么会不相等呢
        //看下面
        str2="ab"+"c";
        System.out.println(str2=="abc");//现在又是true,说明了只要是字符串常量相加,得到的就是字符串常量
    }

}


评分

参与人数 1技术分 +1 收起 理由
黄奕豪 + 1 赞一个!

查看全部评分

回复 使用道具 举报
楼上的朋友,解释很详细。
回复 使用道具 举报
谢谢各位了
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马