String b = new String("1"+"2")这句话在内存里会有几个对象呢有的人说是1个,就一个:new("12")
有的人说是四个,“1”,“2”,“12”,new("12")
还有人说是五个,“1”,“2”,“12”,new("12"),b答案到底是什么呢,小弟在线等权威解答!

解决方案 »

  1.   

    如果说一共产生过几个对象,我觉的是 第二种解释,4个对象。
    如果说最终内存里的对象只有一个,因为("1"+"2")作为参数传递之后的匿名对象会自动销毁,最终只存在对象new("12")一个对象。b只是一个对象的引用,不算对象.
      

  2.   

    String b = new String("1"+"2")
    看样子应该是1,2,12 可是java编译的时候会不会和String b = new String("12")没啥区别呢
    1个
      

  3.   

    恩,不知道jvm会不会做这种优化
      

  4.   

    5个对象包括:
    StringBuilder 1个
    "1" 1个
    "2" 1个
    组合起来,"12" 1个
    new String("12") 1个
      

  5.   


    谢谢你,但我认为肯定得有new这个生成的对象啊!!
      

  6.   


    谢谢啦,怎么StringBuilder 1个  ,这是怎么回事呢?
      

  7.   

    JDK 有自己的优化。
    "1" + "2",这种拼装字符串,JDK会使用StringBuilder.append来拼接字符串。
      

  8.   

    4个。
    "1","2": 2个。
    "1"+"2": 1个,
    new : 1个
    b=直接地址赋值不建立对象。验证程序:public class test {
      
    public static void main(String[] args) {
        
    String a = "1"; String b = "2"; String c = a + b; String d = new String(c); String e = d; System.out.println(a==b);
      
    System.out.println(b==c);
    System.out.println(a==c);
    System.out.println(c==d);
    System.out.println(d==e); }}
    输出结果:
    false
    false
    false
    false
    true
      

  9.   

    如果把JVM背后做的都算上,恐怕5个都挡不住,所以个人意见StringBuilder应该不计入。
      

  10.   

    LZ如果有爱好,可以研究一下JVM。这里有一篇解释相关知识的帖子,LZ可以参考:
    http://blog.csdn.net/fg2006/article/details/6713070
      

  11.   

    搞不懂为什么说"1"+"2"是分开的?
    "1" + "2" == "12";测试不为true?
    new是一个,"1" + "2"是一个(就是"12",在字符串池中),就两个对象;
      

  12.   

    还有点是上面有人说用到了StringBuffer/StringBuilder,这里是没有用到的;
    区分下"1" + "2" 和 "1" + a(这里的a是变量)就清楚了;
      

  13.   

    两个,一个是String对象。,,new String的对象,,,第二个是12,应该在存进内存后,12已经被java优化了。就是计算了。
      

  14.   

    String b = new String("1"+"2")
    首先被编译器优化为String b = new String("12"),注意是编译器,不会运行时!
    然后"12"是一个常量,在类加载时进入常量池中,在运行时生成了一个对象
      

  15.   


    ++我认为也是两个。。一个  "12"  一个new(12)
      

  16.   

    这个问题大家不要想那么麻烦。JVM去做什么都算上的话,那么“对象”的建立是在哪个层次的?Runtime里建立的对象算不算?GC也参加这段代码了那么GC算不算一个对象?在Java语言层次就够了,Runtime或者编译器去做优化的话Rumetime和编译器还有不同版本,是OpenJDK还是Oracle还是Sun的或者是GCJ?不可能做优化的部分都有统一的编码。所以只从Java语言层次再看看LZ最初的3个选项,其他两个显然是不正确的。大概这道题也不会去考这么麻烦的,如果面试的时候你说说你知道JVM偷偷摸摸做了什么当然更好。
      

  17.   

    我个人认为只有2个,首先“1”+“2”会被优化为“12”,并被存放在字符串池中,即第一个。接着由于new在堆中会创建一个String对象。
      

  18.   

    一共就2个具体解释如下:
    对于:String b = new String("1"+"2")
    首先,我们平常创建对象的方式有两种,一个是利用new关键字,另外一个是利用反射机制的newInstance方法。以及String类型的直接“赋值”方法:例如 String str = “1”;
    第二:我们把上面的代码分解为String b, =, new String(), 以及“1” + “2” 四个部分,很显然,String b只是声明了一个名为str的变量,没有创建对象;而 = 是对str进行初始化,把某个对象的引用赋值给str;这样要想要创建对象,就是在下面的两种方式中了。
    第三:对于new String(),以及“1” + “2”,要考虑到字符串连接池的知识,在JVM中存在着由String类管理的字符串连接池,其中保存着很多的String对象,可以被共享使用,提高了效率,同时由于String类都是final类型的,不必担心对象共享带来的混乱。在new一个对象的时候,先去连接池查看是不是有了这么一个对象,没有的话才去创建这个对象。对于“1” + “2”,这种形式的常量连接,是在编译时就确定优化为“12”了,因此里面的“1” + “2”只是创建了一个对象。
    第四:“1” + “2” 是创建了一个对象,那么new String();也创建了一个,因此总共是创建了两个!!
      

  19.   

    很简单
    System.out.println("12" == "1" +"2");
    结果:true
    so..
      

  20.   


    对于java程序中的字符直接量,JVM会使用一个字串池来保存它们。当第一次使用某个字符串直接量时,JVM会将它放入字符串池中进行缓存。在一般情况下,字符串池中的字符串对象不会被垃圾回收。当程序再次需要使用该字符串时,无需重新创建一个新的字符串就可以直接让引用变量直接指向字符串中已有的字符串。而使用new操作创建的字符串对象不指向字符串池中的对象,但是可以使用intern方法使其指向字符串池中的对象对于java程序中的字符直接量,JVM会使用一个字串池来保存它们。当第一次使用某个字符串直接量时,JVM会将它放入字符串池中进行缓存。在一般情况下,字符串池中的字符串对象不会被垃圾回收。当程序再次需要使用该字符串时,无需重新创建一个新的字符串就可以直接让引用变量直接指向字符串中已有的字符串。而使用new操作创建的字符串对象不指向字符串池中的对象,但是可以使用intern方法使其指向字符串池中的对象。
    貌似上面那样不能证明!sorry
      

  21.   

    "1" 是一个对象,“1”是一个对象,“12”为拼接的结果,也是一个对象,还有new String()这也是一个对象,只不过给引用到“12”上了。字符串池中存在“1”,“2”,“12”三个字符串,而且字符串String不是一个基础数据类型,所以说三个字符串是三个对象,只不过由池子统一管理了。new String()毫无疑问,肯定是对象。
    综上:四个对象。
    注:楼上有说StringBuilder对象的,个人对这个不太了解,没有发言权。
      

  22.   

    别人写jvm 我们猜jvm的动作
      

  23.   

    String类是一个特殊的类,字符串内容一旦声明则不可改变,所以应该对堆内存进行分析,应该有4个对象:
    "1"、"2"、"12"、new String() 或者对象b。
    "1","2","12"在堆内存空间中都是匿名对象,一个字符串就是一个匿名对象,所以这里有3个匿名对象。new String()创建新的对象被b引用。
      

  24.   

    最终会产生2个对象“1”+“2” java编译器会自动把他转换成"12" 所以他是一个对象 然后new了一个又一个对象加一起2个
      

  25.   

    这问题还用想,不管new String()里是什么,就只有两个对象的
      

  26.   

    2个,没有StringBuilder或者StringBuffer
    这个大家在这里猜来猜去的没意思,自己写个程序,编译下,然后再拿class文件反编译下就OK了,下面是我反编译的结果public class Test
    {
        public static void main(String[] args)
        {
            String b = new String("1" + "2");
        }
    }
    进入bin目录,执行javap -c -l -verbose Test
    结果如下:Compiled from "Test.java"
    public class Test extends java.lang.Object
      SourceFile: "Test.java"
      minor version: 3
      major version: 45
      Constant pool:
    const #1 = class #2; //  Test
    const #2 = Asciz Test;
    const #3 = class #4; //  java/lang/Object
    const #4 = Asciz java/lang/Object;
    const #5 = Asciz <init>;
    const #6 = Asciz ()V;
    const #7 = Asciz Code;
    const #8 = Method #3.#9; //  java/lang/Object."<init>":()V
    const #9 = NameAndType #5:#6;//  "<init>":()V
    const #10 = Asciz LineNumberTable;
    const #11 = Asciz LocalVariableTable;
    const #12 = Asciz this;
    const #13 = Asciz LTest;;
    const #14 = Asciz main;
    const #15 = Asciz ([Ljava/lang/String;)V;
    const #16 = class #17; //  java/lang/String
    const #17 = Asciz java/lang/String;
    const #18 = String #19; //  12
    const #19 = Asciz 12;
    const #20 = Method #16.#21; //  java/lang/String."<init>":(Ljava/lang/String;)V
    const #21 = NameAndType #5:#22;//  "<init>":(Ljava/lang/String;)V
    const #22 = Asciz (Ljava/lang/String;)V;
    const #23 = Asciz args;
    const #24 = Asciz [Ljava/lang/String;;
    const #25 = Asciz b;
    const #26 = Asciz Ljava/lang/String;;
    const #27 = Asciz SourceFile;
    const #28 = Asciz Test.java;{
    public Test();
      LineNumberTable: 
       line 1: 0  LocalVariableTable: 
       Start  Length  Slot  Name   Signature
       0      5      0    this       LTest;
      Code:
       Stack=1, Locals=1, Args_size=1
       0: aload_0
       1: invokespecial #8; //Method java/lang/Object."<init>":()V
       4: return
      LineNumberTable: 
       line 1: 0  LocalVariableTable: 
       Start  Length  Slot  Name   Signature
       0      5      0    this       LTest;
    public static void main(java.lang.String[]);
      LineNumberTable: 
       line 5: 0
       line 6: 10  LocalVariableTable: 
       Start  Length  Slot  Name   Signature
       0      11      0    args       [Ljava/lang/String;
       10      1      1    b       Ljava/lang/String;
      Code:
       Stack=3, Locals=2, Args_size=1
       0: new #16; //class java/lang/String
       3: dup
       4: ldc #18; //String 12
       6: invokespecial #20; //Method java/lang/String."<init>":(Ljava/lang/String;)V
       9: astore_1
       10: return
      LineNumberTable: 
       line 5: 0
       line 6: 10  LocalVariableTable: 
       Start  Length  Slot  Name   Signature
       0      11      0    args       [Ljava/lang/String;
       10      1      1    b       Ljava/lang/String;
    }
    重点在ldc #18; //String 12,编译器直接给你把2个字符串合并成一个字符串,放在了常量区
    const #18 = String #19; //  12
    const #19 = Asciz 12;纵观整个反编译的结果,没有发现单独的1或者2以上证据足以说明问题了。
      

  27.   


    谢谢你的细致回复,但是我对javap -c -l -verbose Test这个命令如何操作,以及最后生成的内容不是很懂,能不能给出一些简单讲解。小弟在此谢过啦
      

  28.   

    javap是反编译工具JDK提供的一个工具
    在bin目录下
     -c -l -verbose Test
    -c 输出分解后的代码,例如,类中每一个方法内,包含java字节码的指令,
    -l 输出行和变量的表
    -verbose 输出栈大小,方法参数的个数
    Text是反编译的class文件
      

  29.   


    这个解释非常到位,更多的参数可以用javap -?来获得,E文的,耐心看一下,基本就都了解了另外,LZ记得结贴~~