String a = new String("b"); 到底是几个对象呢?

我的答案: 只有一个对象!帖子中回答两个的居多; 而且在baidu google上搜索居然也是回答两个的居多!
大部分认为: 一个是new String()出来的;  一个是"b";
我学java以来,不断的提醒自己 对象是new  new new new !~ 不new 哪里来的对象呢?.我将自己的观点剖析给大家, 如果我的观点错误了,请大家给予反驳:很多人认为"b";是一个对象;  那要从String  这个类说起了!~String  是个引用类型, 引用类型是以对象的形式存在;这句话确实不假!
可是大家已经发现了 new String () 和"b" 没有放在同一个位置; 一个放在堆中; 一个放在池中!
大家认为正常吗?. 对象是可以随便放的吗?. 说到这里可能有人反驳:那又怎么样!~ 以后还要把对象放在栈中!
(有人反驳观点的时候竟然把基础数据类型也当成对象来说!详在后面!)
这样一来, 大家乱放,我们怎么控制其位置啊?.我们要看清楚String池; 它是一个固定的!~ 我们可以从里面取值; 却无法改变它!如果你说那里面的全是对象, 
那我倒想问问那里面有多少对象?. 难道要说不计其数的对象?.说到这里可能有人会说:你的抽象思维有待提高啊!有String池 是不是还有Integer池 是不是还有Boolean池 等等;; 我不信它把对象一个一个都给你创建好了?.创建对象---就是用java提供的new关键字为对象分配存储空间; 这样的对象全部都在heap中; 这样的对象才可以称得为java中的对象;而字符串常量是放在dataSegment中; 方法体也放在这里; 为什么非要将一个字符串常量规定说明为一个对象呢?. 既然是那样!
那还规定常量做什么?. 规定变量做什么?. 人们大肆想象!~ 甚至我可以说对象是个永远不存在的东西算了!~我们在面临逻辑思维思考时是有条件的!~难道你没有学过离散数学的命题逻辑吗?. 在一定的条件下进行推理!说到这里,先将有人将基础数据类型想象成对象的问题说明一下:
他的反驳观点是这样的:

Object o = 5;//可行5,是一个int类型的常量 却变成了一个Object对象; 难道你不认为这个int类型常量也是一个对象吗?.
基础数据类型更不可能成为一个对象了!~ 不信你去instanceof一下!~
一个是引用类型; 一个是基础数据类型; 连类型都不相同; 怎么可能会是一个对象?.
说到这里有人可能疑惑了; 那上面可行啊!~你这不是胡说吗?. 那要看它里面的运行过程了!~
我们都知道java将基础数据类型全都给了包装类!目的就是为了实现基础数据类型与引用类型之间的交换!说到交换, 大家看下面的一组例子:

int i1 = 5; 
Object o = 5;
Integer i2 = 5;  
Integer i3 = new Integer(5);
Integer i4 = new Integer(5);i1 == i2; i1 == i3; i1 == i4; i1 == o; i2 == o;//true 
i2 != i3 i3 != i4  o != i4;//true
从上面可以看出 o已经变成了一个Integer类型的 Object类型 对象;
这里全是引用类型!~ Integer 不是基础类型, 而是引用类型; 
但是5只是一个int类型的常量, 不管你声明的是什么?... 

解决方案 »

  1.   

    偶个人认为,应该有个前提就是:String a = new String("b");改语句是首次执行,也就是说String池里还没有"b"。那执行过后,String池里一个对象,堆上一个对象。如果执行此语句前String池里已经有了"b",结果就只创建一个对象。
      

  2.   

    我见到有人这样的回答:
    实际上,对于所有用双引号括起的字符串常量,系统会把它创建一个无名的String类型对象。 
    当我们打开API 去翻阅时, 发现String 的构造函数!~~new String("b")  与 "b" 完全无法相等!~~  而 "b" 与 "b" 完全 ==如果它是按照String类创建的一个无名String类型对象 ;  它会脱离String类的限制吗?>
      

  3.   

    那么大家就更要看看下面这个该是几个对象了:

    StringBuffer a = new StringBuffer("bbbbbb");

    聪明的人快来解释解释!~~~~~~~~~
      

  4.   

    楼主你已经走火入魔了!首次执行 String   a   =   new   String("b"); 创建2个String对象。1、String池中的"b",也叫做匿名String对象。
    2、因为有"new"关键字,所以复制一份对String池中匿名String对象的拷贝,在堆上创建String对象,并返回引用给a。
      

  5.   

    同意,肯定走火入魔了。
    那么String s = "B";就是说,根本没有对象啦!!!!! 我倒,我去死!
      

  6.   

    是吗>,, 那这样来看看!~
    new String()  与 ""  与null   它们三种有会 ==的吗?. 
    象你所说的String 池  那有没有Integer池?.
    要不然:  Integer i1 = 5; Integer i2 = 5   i1 == i2;
    这个就不会成真了啊!~~
      

  7.   

    我们去调用Sting类里的任何一个构造方法; 是不是对象绝对不会产生在String池里了?>难道API里的String类 将那一种特殊的构造方法给屏蔽掉了; 不想让我们看到?>
      

  8.   

    虽然从JVM机制上讲,String类型的对象更像一个常量而StringBuffer类型的对象接近于C++中的String变量,但是绝对不代表String池中放就不是对象.5楼的回答很准确,对象就是对象,无论Java对它的使用有多么特殊,String池中放的是字符串对象而非其他东西.
      

  9.   

    没有Integer池,只有String池,Java中没有String基本类型Java对String采取了特殊的处理方式,才使得这个争论出现 Object o = 5;  这个例子在1.4的JDK中应该会出错.因为1.5的JDK新特点之一正是 Integer包装类和int基本类型之间的转化自动完成.
    Object o = 5;在1.4及其之前必须这么做:int i = 5;
    Object o = new Integer(i);
      

  10.   

    其实干脆怎么讲吧:因为Java中没有String这个基本类型那么字符串(我是说字符串)一旦出现,并且被赋予一个引用,那么必然诞生了至少一个对象.
      

  11.   

    有一种说法是Java并不是非常纯粹的面向对象,因为Java里还有基本数据类型,而基本数据类型不是对象.不过String并不包括在基本数据类型里面....
      

  12.   

    JDK1.5之后出现了基本类型向引用类型转换的自动打包,拆包机制(也就是C#中的装箱、拆箱)。
    但这个实现是基于编译器的,不是基于JVM的,也就是说:Object o = 5;这行代码,编译后就成了Object o = new Integer(5);JAVA的泛型机制也是这样实现
    的。基于性能和其它方面的考虑,JAVA对包装类也进行了特别处理,包装类是不可变类。楼主看到的这个为真 “Integer   i1   =   5;   Integer   i2   =   5       i1   ==   i2; ” 也就不奇怪了。
      

  13.   

    突然发现,楼主似乎把String也当作了基本数据类型,所以才有那么大的争议:
    在这里贴一点Java的基本数据类型:Java语言提供了八种基本类型。六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型。 
    1、整数:包括int,short,byte,long 
    2、浮点型:float,double 
    3、字符:char 
    4、布尔:boolean有Sting吗?没有为什么从JDK1.0开始我们可以 String str = "Hello World!" 这么做呢?
    因为Java或者说JVM把String做了一个特殊的处理,也就是String池的机制.
    这个再详细讨论就走远了,不如记死它:"字符串(我是说字符串)一旦出现,并且被赋予一个引用,那么必然诞生了至少一个对象."
      

  14.   

    我也觉得我已经走火入魔了!~  那按照你的解释  , 请解释一下下面这个现象:

    String s = 1 + 2 + new String("abc");
    String ss = "3abc"s == ss //false ;
    按照你对象的解释  s 是放在 heap中呢?. 还是放在了String池中呢?>.
      

  15.   

    String s = 1 + 2 + new String("abc");
    在这段代码中,因为出现了基本类型自动转换为String类型(我囧,忘记这是从JDK哪一版开始支持的功能了);
    所以编译的时候Java其实进行了下面的处理:
    StringBuffer s_buffer_1 = new StringBuffer( new Integer("1").toString() );
    StringBuffer s_buffer_2 = new StringBuffer( new Integer("2").toString() );
    StringBuffer s_buffer_abc = new StringBuffer( new String("abc") );StringBuffer s_buffer = s_buffer_1 + s_buffer_2 + s_buffer_abc;
    /**
     * Java中所有String的变化,都是先转变为StringBuffer完成,最后在转变回String
     * 这就是为什么当一个字符串经常变动的时候,推荐使用StringBuffer的原因
     * 并且,一般而言StringBuffer的效率高于String
     */
    String s = s_buffer.toString();看到最后一行,s怎么来的? 调用了StringBuffer 中的 toString()方法;
    查看源代码,StringBuffer中的toString()方法:public synchronized String toString() {
      return new String(value, 0, count);
    }
    也就是说,这个String是new出来的,其实楼主的例子相当于:String s = new String("3abc");
    String ss = "3abc" ;boolean boo = (s == ss);   //false 
    一个是new的引用,一个在对象池中,当然不一样了,boo最后为false也可以理解了吧.
      

  16.   

    晕,咋越搞越复杂了呢。String s = 1 + 2 + new String("abc");先执行算术运算1+2=3,再用StringBuffer连接字符串并返回一个新的String对象给s。一个在堆上,一个在String池里,比较“==”肯定返回false了。楼上的貌似也跟着走火入魔了~~~
      

  17.   

    想左了想左了啊....的确是执行的String s = 3 + new String("abc");头脑一热就彪了...
      

  18.   

    你们的解释越来越离奇, 那再来试试这个吧!~
    看看还是不是new String()了:

    String s1 = "abc";
    String s2 = "abc" + s1 ;
    String s3 = "abcabc";s2 == s3  //false;
     难道s2 是new出来的?.  在 heap中?...  让我来听听你的解释!~~~
      

  19.   

    难道s2   是new出来的?是的, s2 就是 new 出来的,难道你不知道吗??? 
    + 被重载了
      

  20.   

    有的实现是StringBuilder b = new StringBuilder("abc");
    b.append(s1);
    String s3 = b.toString();
      

  21.   

    楼主确实是生成了2个对象,heap中生成的对象,另外一个是String池里的对象,如果直接写成String s = "b";而不使用封装类,那确实是只生成了1个对象;
      

  22.   

    不好意思! 又要推翻你们了:

    竟然说 + 被重载了!~  你再试下面的!:String s1 = "abc" + "abc";
    String s2 = "abcabc";
    s1 == s2 //true"abc" 是对象, 一 "+"  也重载了吗?. 为什么不重载?. 谬论啊!~
      

  23.   

    感觉上:1. “+”不是重载的,java不能重载运算符。2.
    String s1="abc";String s2="abc"+s1;   中s1是通过引用的对象,构建s2时会调用new事件,所以产生新对象;String s3="abc"+"abc";  中是无引用对象,不会调用new事件,不产生新对象,而只是产生了一个String池中的 对象"abcabc";当再增加一句  String s4="abcabc"; 此时池中已经有"abcabc"对象,只是把s3指向了池中的"abcabc"对象,所以会出现s2==s3; //falses2==s4; //true下面是Java的帮助里的说明:
    Java 语言提供对字符串连接操作符 ( + )和其它字符串对象相互转换的特殊支持。 字符串连结是通过 StringBuffer 类和它的 append 方法实现的。人家说了是特殊支持再说,我一直不认为只有用new new new new new 才能产生对象,楼主不要太死板
    我举个例子:
    对象克隆(clone),它产生的是一个新对象,而且没用到new关键字(这个例子虽然有点跑题)
      

  24.   

    有关于String 的一些材料http://blog.csdn.net/zyongsheng83/articles/1723028.aspx其中提到了:
    而”kv”和”ill”也都是字符串常量,当一个字符串由多个字符串常量连接而成时,它自己肯定也是字符串常量,
    所以s2(原文中有:String s2="kv"+"ill"; )也同样在编译期就被解析为一个字符串常量,所以s2也是常量池中”kvill”的一个引用。
    个人觉得里面的例4是错的,因为第一句中String s1=new String("kvill"); 的"kvill"在编译的时候就在常量池中产生了,所以第三句肯定为false,
    因此这个例不能用来证明以下观点错误:
    “使用String.intern()方法则可以将一个String类的保存到一个全局String表中,如果具有相同值的Unicode字符串已经在这个表中,那么该方法返回表中已有字符串的地址,如果在表中没有相同值的字符串,则将自己的地址注册到表中”
      

  25.   

    to 楼住:26 的说法
    请大家看这段代码
      public static void main(String[] args) {
        String s1 = "abc";
        String s2 = "abc" + s1;
        String s3 = "abcabc";    System.out.println(s2==s3);
        
        String   s11   =   "abc"   +   "abc"; 
        String   s22   =   "abcabc"; 
        
        System.out.println(s11==s22);
      }运行结果
    false
    true我们再看编译后的文件
        public static void main(String args[])
        {
            String s1 = "abc";
            String s2 = (new StringBuilder("abc")).append(s1).toString(); // 请注意这里,+ 被重载了
            String s3 = "abcabc";
            System.out.println(s2 == s3);
            String s11 = "abcabc";  // 请注意这里,编译器的优化机制自动将他们合并了
            String s22 = "abcabc";
            System.out.println(s11 == s22);
        }
    OVER
      

  26.   

    to 27楼
    感觉上: 
    1.   “+”不是重载的,java不能重载运算符。 
    java是不能让用户重载运算符,但是他自己可以用,+ 就是典型1+1 
    "1"+"1"
    1.0 + 2.0明明被操作的对象不同,可是依然能用,这就是java的运算符重载。 很可惜,java不对用户开放这个功能。    Object o1=null;
        Object o2 = null;
        Object o3 = o1 + o2;编译错误。
      

  27.   

    29和30楼回答得很明确了....
    1.String不是基本类型,一旦有字符串被赋予引用,就至少有一个对象.2.String池中的字符串也是对象.3.只有String的"+"操作,编译时被优化了,其实JVM没有进行任何操作.4.一旦String进行了"+"操作,Java是用StringBuffer完成,最后结果会用new声明一个新对象.
      

  28.   

    当String s = "abc" + "abc";的时候 看class文件:
      public static void main(java.lang.String[] args);
        0  ldc <String "abcabc"> [16]
        2  astore_1 [s1]
        3  return
          Line numbers:
            [pc: 0, line: 24]
            [pc: 3, line: 31]
          Local variable table:
            [pc: 0, pc: 4] local: args index: 0 type: java.lang.String[]
            [pc: 3, pc: 4] local: s1 index: 1 type: java.lang.String
    当String s1 = "abc"; String s2 = "abc" + s1;的时候 再看class文件:  public static void main(java.lang.String[] args);
         0  ldc <String "abc"> [16]
         2  astore_1 [s1]
         3  new java.lang.StringBuilder [18]
         6  dup
         7  ldc <String "abc"> [16]
         9  invokespecial java.lang.StringBuilder(java.lang.String) [20]
        12  aload_1 [s1]
        13  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [23]
        16  invokevirtual java.lang.StringBuilder.toString() : java.lang.String [27]
        19  astore_2 [s2]
        20  return
          Line numbers:
            [pc: 0, line: 24]
            [pc: 3, line: 25]
            [pc: 20, line: 31]
          Local variable table:
            [pc: 0, pc: 21] local: args index: 0 type: java.lang.String[]
            [pc: 3, pc: 21] local: s1 index: 1 type: java.lang.String
            [pc: 20, pc: 21] local: s2 index: 2 type: java.lang.String
    }
    在编译的时候就做了不同的处理,很明显String s = "abc" + "abc";被优化为 String s = "abcabc";
      

  29.   

    个人认为先要定义好java的对象到底怎么判断的,是根据是否会被引用判断 还是根据内存中的数据存储位置判断。
    另外好像这样的问题也没多大意义,在项目当中能搞清不同的构造字符串方法存储的位置不同就可以了。没见过谁在做项目时非要搞清楚这个String到底是不是对象。或许sun自己也没搞清楚也说不准 哈哈
      

  30.   

    共享池(数据池/stack)里一个,new出来一个。。一共2个。。 楼主是不是火星。。
      

  31.   

    对了,我32楼第3点和第4点也有点问题:Java编译会优化所有String + String 以及 String + 基本数据类型常量 的操作,直接完成.比如 String s = "abc" + 1; 也会优化为 String s = "abc1";(注意,只有这个顺序会优化).
      

  32.   

    楼主的说法还是有一定的道理的,字符串常量并不能算是完全的对象,java的内存区分为:方法区,堆,栈,本地方法调用区,对像是放在堆里的,而常量,静态变量等是放在方法区内的
      

  33.   

    回39楼: 在java中除了8中基本类型外,其他的都是类对象以及其引用.
      

  34.   

    "Hello World"在Java中,无论它怎么来的,都是一个String对象.
      

  35.   

    非常好,在Java版很少能看到这么好的帖子.支持.
    我没有一个明确的答案的.因为我对此研究不够深入.我最近几个月在研究Lex & Yacc,也看过一些Kaffe的源码,其实诸位讨论的东西,也许在Sun,或者IBM的JVM上,或者某种JVM上有着不同的表现的.
    通常来讲,cangyue87说得非常对,在编译阶段,字符串字面量就已经被合并了.这个在语法分析和语义分析阶段就可以完成了(个人猜测).
    日后有空可以把这段Yacc脚本paste上来.举几个不恰当的例子,std::string是C++的标准库中的string类,在不同的实现版本中有着非常大的差别.
    有的是使用RefCount(引用计数)和COW(Copy on write)技术的实现的,有的则是走memcpy的.具体的差异和成因就不细说的.
    我想说得是Java的String结合了这两种实现的优点,在不断的进化中,可能有着不同的实现,那么是一个对象,还是两个对象就说不清楚了.
    唯一能说清楚的就是某一个版本的Java的同样代码是怎样的.
    讨论中提到的重载,或者是其他的问题,这些都是Java语法层面上的东西,看起来也许有new的过程,但是实际上也许没有,但是这些都是实现上的问题.
    如果能看到它真正的源码,(包括Yacc语法分析文件在内)才能把这个事情说清楚的.因为即便我们看到了ByteCode了,也不能认为它描述的就是一个真理,因为JVM的优化是更加隐蔽的,更加底层的东西了,可以猜想同样的代码,
    在第一次和第二次运行的时候就可能有着不同的内部流程.那么这个是几个对象被创建了呢?技术上,讲究能"进得去",也能"出得来",所谓进得去就是可以深入的研究.出得来就是指在深入研究后,可以站到更高的角度看待这些问题.
    我觉得诸位已经很深入了,就不必太看重是一个,两个了,可以走出来了.我觉得讨论就是好的,其实我就是认为没有一个真正的答案的.重要的是在看大家的讨论中学到东西.
    兄弟我的大言不惭就到此为止了,诸位继续.
      

  36.   

    String s="b";
    String s= new String("b"); new 出一个对象、
      

  37.   

    to 楼主:对象不一定是new才出来的说对象只有new才能出来,那纯粹扯淡相信书,但不要迷信书------孙鑫
      

  38.   

    以前我研究缓冲区溢出攻击,我要覆盖栈上保存的ESP的值,我就天天看汇编,调试,是多覆盖了4个字节,还是少覆盖了4个字节?
    后来,试验代码用VS2003,2005一编译,我靠,__chkesp了...不管用了...唉,何必那么执着呢.
      

  39.   


    看来楼主是自学的了,但显然好像还不够通哦...如果有公司问到你这道题,你这样回答的话,我想这家公司应该不会录用你的.至少我是这么想的.其它的不说了,就连这个基本的东西你都搞不清呀:new   String()     与   ""     与null       它们三种有会   ==的吗?.   这几个值相不相等跟有几个对象有关系吗?自己多看看书吧!
      

  40.   

    楼主还是很爱学习的,精神可嘉,就是没有跳出语法的圈子呢.
    Ruby都能写
    3.times{ print "hello" }
    这样的代码,对象不对象的,没有一个确切的说法的.
      

  41.   

    其实是不是对象真那么重要吗,都是应试教育惹来的祸,反正写程序时也不会有什么问题,能搞清楚在内存中分配在哪块区域就很不错了。很多人这个都搞不清还不是一样做项目,什么Struts hibernate还不是一样用的牛X
      

  42.   

    楼主最后一部分的例子举错了!在一定的范围之内:i2 == o 是正确的!确实一些基本类型(除float和double之外)都有常数池,不过都有特定的范围:byte, short, int, long 范围:-128~127
    char范围:\u0000~\u007F
    boolean范围:true和false在上述的范围之外的数据都另外开辟空间进行存储
      

  43.   

    我以前在
    http://topic.csdn.net/u/20070828/10/43260254-04f1-4ac0-9da1-b48af45c2a83.html?1646266974
    回答过这个问题。(29楼)
    哈哈,要理解这个,就要知道string类的工作原理。你知道在java中除了8中基本类型外,其他的都是类对象以及其引用。所以 "xyz "在java中它是一个String对象.对于string类对象来说他的对象值是不能修改的,也就是具有不变性。
    看:
    String   s= "Hello ";
    s= "Java ";
    String   s1= "Hello ";
    String   s2=new   String( "Hello ");啊,s所引用的string对象不是被修改了吗?之前所说的不变性,去那里了啊?你别着急,让我告诉你说发生了什么事情:
    在jvm的工作过程中,会创建一片的内存空间专门存入string对象。我们把这片内存空间叫做string池。String   s= "Hello ";当jvm看到 "Hello ",在string池创建string对象存储它,并将他的引用返回给s。
    s= "Java ",当jvm看到 "Java ",在string池创建新的string对象存储它,再把新建的string对象的引用返回给s。而原先的 "Hello "仍然在string池内。没有消失,他是不能被修改的。所以我们仅仅是改变了s的引用,而没有改变他所引用的对象,因为string对象的值是不能被修改的。String   s1= "Hello ";jvm首先在string池内里面看找不找到字符串 "Hello ",找到,返回他的引用给s1,否则,创建新的string对象,放到string池里。这里由于s= "Hello "了,对象已经被引用,所以依据规则s和s1都是引用同一个对象。所以   s==s1将返回true。(==,对于非基本类型,是比较两引用是否引用内存中的同一个对象)String   s2=String( "Hello ");jvm首先在string池内里面看找不找到字符串 "Hello ",找到,不做任何事情,否则,创建新的string对象,放到string池里面。由于遇到了new,还会在内存上(不是string池里面)创建 string对象存储 "Hello ",并将内存上的(不是string池内的)string对象返回给s2。所以s==s2将返回false,不是引用同一个对象。好现在我们看题目:
    String   s   =   new   String( "xyz ");
    首先在string池内找,找到?不创建string对象,否则创建,   这样就一个string对象
    遇到new运算符号了,在内存上创建string对象,并将其返回给s,又一个对象所以总共是2个对象 
      

  44.   

    此回复为自动发出,仅用于显示而已,并无任何其他特殊作用
    楼主【bxdg42578670】截止到2008-06-23 23:23:17的历史汇总数据(不包括此帖):
    发帖数:23                 发帖分:540                
    结贴数:16                 结贴分:430                
    未结数:7                  未结分:110                
    结贴率:69.57 %            结分率:79.63 %            
    楼主加油
      

  45.   


    String s1 = "abc";
    String s2 = "abc" + s1 ;
    String s3 = "abcabc"; 
    中s1被赋予的"abc"在String池中根据上面高手所说,在给s2赋值的时候发生了
    StringBuffer s_buffer_1 = new StringBuffer( new String("abc") ); 
    StringBuffer s_buffer_abc = new StringBuffer( new String("abc") ); 
    StringBuffer s_buffer = s_buffer_1 + s_buffer_abc;
    String s2 = s_buffer.toString();s2指向了内存中的"abcabc",s3指向了String池中的"abcabc",所以不等
    本来没想明白,等写完回帖明白了,回帖果然是好习惯啊
      

  46.   

    楼主好精神。值得敬佩。
    我刚刚搞明白new string 的问题。觉得是2个对象。。没想到又看到楼主的帖子。我和楼主一起入魔!!!
      

  47.   


    看了大家的回复,我学到了不少东西
    这里提出一点自己的见解String  s  =  new  String( "xyz ");按照56楼的说法,如果找不到就新建一个,这时产生2个对象
    如果找到了,就只创建一个对象,但是xyz既然在池中,
    就说明必然有一个对象是因它而创建,但不是这段代码所创建
    所以说2个对象是对的
    但有一个不一定是这段代码所创建
      

  48.   

    不管有几个对象,我觉得lz没有搞清楚一个问题就是
    ==比较的是内存地址,而equals比较的才是内容,你上面自己举的例子可以推翻了......另:如果公司问这种问题,我答对也不会去..
      

  49.   

    是两个对象,一个是编译时,在字符串常量连接池中创建的"b"对象,一个是运行时根据字符串常量连接池中创建的"b"对象为模板创建的new String("b");对象理由,利用字符串的扣留机制测试一下下面的代码: String m="a";
    String n="b";
    String p=new String("ab");
    String q="ab";
    q=q.intern();
    System.out.println(q==p);
    System.out.println(q=="ab");结果是
    false
    true
    说明创建字符串new String("ab")之前已经先创建了字符串对象"ab"
      

  50.   

    new String("b").里面的"b"是String类型参数,new String("b").是以"b"为基础创建的新的字符串,每次new 都要创建一个新的对象
    new String(new String("b")).一共是几个字符串?
      

  51.   

    其实楼主说的有一定道理:
    String a = new String("b"); 
    这句话是包含了两个字符串,而不是创建了两个字符串。
    因为字符串"b"是编译的时候就已经创建了,运行这句话的时候只是调用这个字符串"b"而已,实际上这句话只是创建了一个字符串,而"b"是编译的时候创建的,而不是运行这句话的时候创建的,有点咬文嚼字的嫌疑
    另外说明一下1+2+"ab"编译是通不过的,只能是""+(1+2)+"ab",即只能是字符串加别的,不能别的加字符串而且是从左到右,变成了字符串
      

  52.   

    经典,大家把java的自字符串的产生剖析得淋漓尽致