原帖:
http://community.csdn.net/Expert/topic/3898/3898233.xml?temp=.7976496==============================================================================
哈哈。我认为是对的。相信有很多人不清楚。
一个是new 出来的。被s引用着;
还有一个是"xyz",这个也是一个对象!实际上java先为字符串常量创建了无名字符串对象。然后在通过new String创建一个新的String对象

解决方案 »

  1.   

    问你 String s=new String("xyz");这条语句创建了几个对象 ?
      

  2.   

    当然只能是一个对象一个new只能创建一个对象起码的规则。
      

  3.   

    好早就讨论过了哈(1)我们在使用诸如String str = "abc";的格式定义类时,总是想当然地认为,我们创建了String类的对象str。担心陷阱!对象可能并没有被创建!唯一可以肯定的是,指向String类的引用被创建了。至于这个引用到底是否指向了一个新的对象,必须根据上下文来考虑,除非你通过new()方法来显要地创建一个新的对象。因此,更为准确的说法是,我们创建了一个指向String类的对象的引用变量str,这个对象引用变量指向了某个值为"abc"的String类。清醒地认识到这一点对排除程序中难以发现的bug是很有帮助的。  (2)使用String str = "abc";的方式,可以在一定程度上提高程序的运行速度,因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于String str = new String("abc");的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象,从而加重了程序的负担。这个思想应该是享元模式的思想,但JDK的内部在这里实现是否应用了这个模式,不得而知。
      

  4.   

    String s=new String("xyz");new String("xyz"); 创建了一个对象String s=  如果不是String ,这里只有引用,没有新创建对象!但是String不同,他不但创建了引用句柄,而且这个句柄并不指向new String("xyz")创建的对象!而是参照new String("xyz")创建的对象另外给自己做了个新对象!!!;其他的object XXX=new object();是只创建一个对象的!String 和StringBuffer的区别能很明显地表现出着一点!
      

  5.   

    对于s=s+"a"+"b"+"c";这种例子有句话很经典(好象是9哥说的):
      String不停的创建对象,StingBuffer不停地改变自己!
      

  6.   

    new String("xyz")
    创建的是一个对象,而"xyz”也是一个对象没错,但是它的创建和这条语句是没有关系的。它是程序String Pool中的一个对象,可能在使用这条语句前很久就已经创建出来了。
      

  7.   

    不知楼上的几位有没有看清楚:  wenchaohu213(夏吾) gary_choi()  jihanzhong(逍遥) 
    ==================
    一个是new 出来的。被s引用着;
    还有一个是"xyz",这个也是一个对象!"xyz"就是一个无名对象啊!也是由java创建的!to: gary_choi() 
     创建了几个对象是由java做的。 不如何!我不赶把它怎样!!to: 007remember(绿原)
     你的那段文字我不止看到3次了。你去看看java里有关字符串的描述:
     “...在java中,用双引号括起来的字符串是字符串常量;又称无名字符串对象,由java自动创建”to: jihanzhong(逍遥)
      object XXX=new object();是只创建一个对象的!
      你说的很对。我也这么认为。它只创建了一个对象。可现在的情况是:
      String s=new String("xyz");//不知道你有没有看到"xyz"这个东东;它也是一个对象啊!to: nimifeng
      这是您的自由,保持!
      

  8.   

    to: Polarislee
    这是String构造函数中的一个参数啊。怎么说没关系呢?不理解。 请指点;还有就是 假如 Pool里没有"xyz"这个对象呢?他照样也会在执行 语句String s=new String("xyz");时一起创建
    如是这样说的话。那它只能说有可能创建2个对象吗?(就是要看pool里有没有)
      

  9.   

    String S=null;//几个对象?---------------------------
    Strind s=new String();//可以这样么?---------------------------String s1="cddf";
    String s2=s1;
    //一共几个对象?-------------------------------------
    object XX=new object("初始值");//几个对象?------------------------------------------object X1=new object("初始值");
    object X2=X1;
    //一共又是几个对象?
      

  10.   

    呵呵 pool到底是什么?
      

  11.   

    回复人: dick66(狒狒) ( ) 信誉:100  2005-05-12 19:57:00  得分: 0  
     
     
       创建了一个对象!!  一个是句柄,一个是对象!!
      
     
    是的,双手赞同!
      

  12.   

    re: jihanzhong(逍遥)String S=null;//几个对象?                      0---------------------------
    Strind s=new String();//可以这样么?            可以---------------------------String s1="cddf";                               可能1(要看池里有没有"cddf")
    String s2=s1;                                   0
    //一共几个对象?                          共计:可能1-------------------------------------
    object XX=new object("初始值");//几个对象?     可能2个,至少1个。------------------------------------------object X1=new object("初始值");                 可能2个,至少1个。
    object X2=X1;                                   0
    //一共又是几个对象?                            可能2个,至少1个。
    =========================================================================
      

  13.   

    to jihanzhong(逍遥)你不需要问这么多问题。只要清楚:
    String s1="cddf"; 这个创建了几个对象就是了。如果String pool里已经有了"cddf",那这条语句仅仅创建了一个String类的reference
    但是如果没有的话。java编译器首先是创建一个字符串常量(要知道这也是一个类,一个匿名类)"cddf"
    建好了后再把这个匿名类的地址给s1。    你能理解我说的意思么?
      

  14.   

    写错了:  改
    建好了后再把这个匿名类的实例"cddf"的地址给s1。    你能理解我说的意思么?
                ^^^^^^^^^^^^
      

  15.   

    这个问题的关键在于: String字面量(即双引号括起的字符串)本身是一个对象.比如我们赋值: String s = "abc"; 这时已经创建一个对象"abc"了, 只不过它是由JAVA自动创建, 而 int i = 1; 就没有创建对象, 因为字面量1不是对象, 是原始类型.但是JAVA对String字面量的创建做一些优化, 为了避免相同的字符串字面量被重复创建, 它使用了String Pool, 在String Pool中, 存储了已经创建的字符串, 所以, 一个字符串字面量始终只创建一次.所以:
    String s1 = new String("abc"); 
    //创建二个对象, 一个是"abc", 一个是包裹"abc"的String对象String s2 = new String("abc"); 
    //创建一个对象, 因为"abc"已经被创建了, 不再重新创建
    而下面的代码:String s1 = "abc"; 
    //创建一个对象"abc"String s2 = "abc"; 
    //没有创建新的对象, 只是将s2也指向"abc".
      

  16.   

    re: jihanzhong(逍遥)不用谢 0_-!!
    相互学习。我也是几天前看到相关资料后阐述的自认为正确的观点。把它放到网上来。
    和大家一起切磋。每次讨论,都会有新的收获。我也更加相信自己的观点。0_-!!共同进步!
    re: Dan1980  那:
    String s1 = "def";
    String s2 = "def"
    创建了几个对象呢?(现在假设String pool里原先没有"def");
      

  17.   

    re wanghongtaoleifeng(小声点)Pool是什么? 翻翻英汉字典。 
    自己动手,丰衣足食
      

  18.   

    re: Dan1980  那:
    String s1 = "def";
    String s2 = "def"
    创建了几个对象呢?(现在假设String pool里原先没有"def");
    -------------------------------------------------------------
    创建了一个对象, 即"def".
      

  19.   

    我想问问 Dan1980(也该有一些作为了)
    您所说
    =============================================================
    String s1 = new String("abc"); 
    //创建二个对象, 一个是"abc", 一个是包裹"abc"的String对象
    =============================================================
    创建的"abc"本来就是一个String对象,为什么还要创建一个  包裹"abc"的String对象
      

  20.   

    re:  Dan1980那String a = new ("abc");呢 ?
    不就是2个对象了么 ?
      

  21.   

    To: FBug(花知) 那String a = new ("abc");呢 ?
    不就是2个对象了么 ?
    //-----------------------
    答: 如果Pool里已经有了"abc",则不创建新对象,引用a指向"abc"文字量
        如果Pool里没有"abc",则在Pool中自动创建"abc"文字量,然后引用a指向它.总之,这一句或者没有创建新对象,或者创建1个,绝不会是2个! Dan1980(也该有一些作为了) 说的对!
      

  22.   

    re: xtaotao(淘淘)
    去看看有关String s = new String("string");的说明吧。
    不管Pool里有没有"string";都会生成一个新的对象的。这样写清楚些:
    String stemp = "string";     //这里才是你所谓的可能创建了一个对象。
                                 //要看String Pool里面有没有了。
    String s = new String(stemp);//这里是100%回Create出一个Object的。知道吗?
                                 //这是一个非常基础的问题。。
    再告诉你一点:
      Dan1980 说的和 你 说的是两回事。
      不过你们两个结合一下就对了。
      

  23.   

    to zhangqingqi82(上下而求索……)收到你的悄悄话了,我不想多说了,请大家去看《Effective JAVA》中的第四条:"Avoid creating duplicate objects"没这本书的或者E文不太好的,我把部分段落草草翻译了一下,贴在下面供大家参考:-----------------------------------------------------------------
    选自<Effective JAVA> 原著: Joshua Bloch 翻译:Dan
    -----------------------------------------------------------------
    第四条:避免创建重复的对象以重用单个对象来代替每次需要时都创建一个新的功能相当的对象通常是合适的。重用可以既快速又更时髦……作为一个不这样做的极端的例子,考虑下面的语句:String s = new String("Silly");  //DON'T DO THIS!这条语句每次被执行时都创建一个新的String实例,并且那些对象的创建中,没有一个是必需的。作为String的创造器的参数"Silly"本身是一个String实例, 功能与每次由创造器创建的对象完全一样。如果这种用法发生在一个循环结构或一个频繁调用的方法中, 数以百万的String实例会不必要地被创建。改进版本很简单地如下:String s = "No longer silly";这个版本使用一个单一的String实例,而不是每次执行都创建新的对象。而且,它保证了对象将被在同一个虚拟机上运行的正好在使用同一个字符串字面量的其它代码重用。
      

  24.   

    我补充一下,也就是说:任何情况下都不要使用类似于String s = new String("Silly");这种方法来创建String,至于JAVA为什么要提供一个这样的构造方法,可能是为了和Integer, Character等一系列包裹类统一起见。
      

  25.   

    是两个对象  不然也 不会有StringBuffer
      

  26.   

    String str1="123";//在缓冲池中创建值为"123"的匿名有id的实例,如id=151String str2=new String("123");//创建str2的实例value的id指向  151结:这种情况下String str2=new String("123");是只创建一个实例,而"123"在str1中已被系统分创建了,并给予了id.String str3=new String("abc");//创建了str3的实例并缓冲池中创建值为"abc"的匿名有id的实例,
                                    如id=152
    String str4=new String("abc");//创建了str4的实例,并value的id指向  152结:这种情况下String str3=new String("abc");创建一个实例,并系统创建值为"abc"的匿名有id的实例,即创建两个实例.而String str4=new String("abc");因为str3已建了"abc"所以它只建了一个实例.
      

  27.   

    总结:当包装的字符串之前没有被使用过即没有被创建过,new String("xxx");创建了两个实例.反之new String("xxx");只为自己创建了一个实例.请楼主仔细看看!!!!
      

  28.   

    “Dan1980(也该有一些作为了)”说得对String s = new String("Silly"); 调用了String(String original)这个构造函数,当String 池中没有这个对象时,是创建了两个对象。
    看看这个例子:String str1 = "hello!";
    String str2 = new String(str1);
    str1 = "hello, world!"  //并非修改str1对象的值。看似修改str1的值,其实是创建一个新对象,然后修改str1之引用可以看出,想修改一个String对象内部的值可不太容易(trim()、toUpperCase()等都不会修改String对象本身的值),所以JAVA String对象本质上是不变的常量,除非有充分的理由需要显式创建一个String对象的副本,否则没有必要使用new String(xxx)。
      

  29.   

    这个并不重要,因为java是运行时优化,肯定是生成的对象越少越好,String本身不能改变内容,所以做一个常量池是很有可能的
    唯一要注意的是当比较字符串的时候,比较引用是很危险的,要用equals
      

  30.   

    补充一下:有创建一个常数的副本的必要吗?比如定义
    final int PI = 3.14;
    final int PI_BAK = 3.14;上述代码没有必要。同理:所以也就没有必要使用new String("xxx")来创建一个String对象的副本。
      

  31.   

    总结:当包装的字符串之前没有被使用过即没有被创建过,new String("xxx");创建了两个实例.反之new String("xxx");只为自己创建了一个实例.
    -------------------
    这个并不重要,因为java是运行时优化,肯定是生成的对象越少越好,String本身不能改变内容,所以做一个常量池是很有可能的
    唯一要注意的是当比较字符串的时候,比较引用是很危险的,要用equals同意!!!
      

  32.   

    to : Dan1980(也该有一些作为了) 
    非常感谢您提出的宝贵资料。但我看了之后并还不确信我的观点是错误的。
    我就要下班了。等我做测试后在给您汇报结果 0_-!!
    to: wa0clever(不懂→问) 
    String str3=new String("abc");//创建了str3的实例并缓冲池中创建值为"abc"的匿名有id的实例,
                                    如id=152
    String str4=new String("abc");//创建了str4的实例,并value的id指向  152
    告诉你。你错了。看看Dan1980翻译的资料吧。re llihua(Hill)
    您在上面回复到:  "String s = new String("Silly"); 调用了String(String original)这个构造函数,
       当String 池中没有这个对象时,是创建了两个对象。"
    --这是我的观点.呵呵。。看仔细了。   final int PI = 3.14;
       final int PI_BAK = 3.14;
    --这是基本数据类型。和Object(String)不同。不能先比较。
      

  33.   

    re: antzl(philozl)   0_-!!
    re llihua(Hill)
       您在最后说的是 有没有必要么?
       哦。是我理解错了。
       不过我们现在讨论的是当在重复定义的情况下。它怎么做。并不是必要不不要的问题。
       还有就是,假如在一个循环体里面呢?重复定义并非是我们的意愿。
       但如果疏忽的话。。呵呵。~~~
      

  34.   

    To 楼主:
    谢谢你的指教,让我认真去考虑问题,我把String类的构造方法复制过来,大家看看,
    我是有点迷惑了.2种情况下一种创建新数组,而另一种情况直接赋值了.    public String(String original) {
      this.count = original.count;
      if (original.value.length > this.count) {
          // The array representing the String is bigger than the new
          // String itself.  Perhaps this constructor is being called
          // in order to trim the baggage, so make a copy of the array.
          this.value = new char[this.count];  //????????????????
          System.arraycopy(original.value, original.offset,
           this.value, 0, this.count);
      } else {
          // The array representing the String is the same
          // size as the String, so no point in making a copy.
          this.value = original.value;  //?????????????
      }
        }
      

  35.   

    的确是创建了两个对象啊!一个是xyz本身。别一个是s对xyz的引用.
      

  36.   

    to : Dan1980(也该有一些作为了)   不好意思。下午我就要下班。没仔细看。
       你写了这么多。不是给我的观点做立论么? 你先看我的观点;后在发表您的观点好么?
       ------------------
       光:
       String s1 = new String("abc");
       String s2 = new String("abc");//创建了两个对象。
       光:
       s1 = "abc";
       s2 = "abc";//创建了一个对象。  
       --------------------------------------我一直都这么认为的。
       仅这句: String str = new String("asdf");
         先创建"asdf";这是一个。//有疑义么?假设Pool里面没有。
         后做参数初始化新对象,并把地址给str;//无论如何,它都会new出一个对象来。
         那不就是有两个了?(假设Pool里没有,否则只有一个。)
    to :onlyxu(未透露姓名男子)
       这里不讨论有没有实际意义。只讨论它的做法。
       对于农民来说。学java没有实际意义  0_-!!
      

  37.   

    re:  xtaotao(淘淘)
    this.value = new char[this.count]; //你把String 理解为 char[]就通了。
                                       //或看看前面关于value的定义.
    this.value = original.value;       //这里我认为仅一个引用;
    一个非常恐怖的结果:
    ===============================================
    public final class Strng {    private final char value[];
        private final int count;    public Strng() {
            count = 4;
            value = new char[] {
                'a', 'b', 'c', 'd'
            };
        }
        public Strng(Strng original) {
            int size = original.count;//为何这里能访问count;
            char[] originalValue = original.value;
            char[] v;
            if (originalValue.length > size) {
                v = new char[size];
                System.arraycopy(originalValue, 0, v, 0, size);
            } else {
                v = originalValue;
            }
            this.count = size;
            this.value = v;
        }
        public String toString() {
            return new String(value);
        }
        public void change() {
            value[count-1] = 'O';
        }    public static void main(String[] args) {
            Strng s1  = new Strng();
            Strng str = new Strng(s1);
            s1.change();
            System.out.println(s1);
            System.out.println(str);
        }
    }
    ===============system.print:========================
    D:\MyJava\CSDN>javac Strng.javaD:\MyJava\CSDN>java  Strng
    abcO
    abcO不过我又做了一个测试:发现很是矛盾
    public class StringTest {    public static void print(char[] chr) {
            for(int i=0; i<chr.length; i++) {
                System.out.print(chr[i]+"-");
            }
            System.out.println("");
        }
        public static void main(String[] args) {        char v[];
            char val[] = {
                '1', '2', '3', '4', '5', '6', '7'
            };        String s0 = "abcd";
            String s1 = new String("abcd");
            String s2 = new String("abcd");
            String s3 = new String(s1);
            String s4 = new String(s2);        System.out.println(s0==s1);
            System.out.println(s1==s2);
            System.out.println(s1==s3);
            System.out.println(s2==s4);        v = val;
            val[3] = 'A';
            print(v);
            print(val);
            System.out.println(v==val);
        }
    }
    ===================================傻了吧。两个结果反映两个观点!
    D:\MyJava\CSDN>javac StringTest.javaD:\MyJava\CSDN>java  StringTest
    false
    false
    false
    false
    1-2-3-A-5-6-7-
    1-2-3-A-5-6-7-
    trueD:\MyJava\CSDN>
      

  38.   

    可以肯定是两个   好象是一道 Java的面视题
      

  39.   

    public class Test{
    public  static void main(String[] args){
     
      String a="abc";
      String b="abc";
      System.out.println(a==b);}
    }--------------
    true
    确实a和b都是一个对象
      

  40.   

    编号: 1 发送者 me5572 发送时间 2005-5-17 23:28:31 删除  回复  
    内容 String a = new ("abc");
    是不是写错了? 
    ======================================================
    to: me5572   呵呵。。献丑了。
      代表毛zx向大家道歉。
      

  41.   

    to 花知:
    public class StringTest {    public static void print(char[] chr) {
            for(int i=0; i<chr.length; i++) {
                System.out.print(chr[i]+"-");
            }
            System.out.println("");
        }
        public static void main(String[] args) {        char v[];
            char val[] = {
                '1', '2', '3', '4', '5', '6', '7'
            };        String s0 = "abcd";
            String s1 = new String("abcd");
            String s2 = new String("abcd");
            String s3 = new String(s1);
            String s4 = new String(s2);        System.out.println(s0==s1);
            System.out.println(s1==s2);
            System.out.println(s1==s3);
            System.out.println(s2==s4);
            System.out.println(s0);
            System.out.println(s1);
            System.out.println(s2);
            System.out.println(s3);
            System.out.println(s4);
            v = val;
            val[3] = 'A';
            print(v);
            print(val);
            System.out.println(v==val);
        }
    }结果:
    false
    false
    false
    false
    abcd
    abcd
    abcd
    abcd
    1-2-3-A-5-6-7-
    1-2-3-A-5-6-7-
    true
    ======================
    四个s是一样的耶
      

  42.   

    是啊。
    是一样的呀。!!"==" 做的地址的比较。并不是值的比较。你把String 理解为一个Object就是了。
    它里面有一个toString()的方法。
      

  43.   

    to  Dan1980非常高兴得到了您的解答,首先表示感谢不过我想重申一下我的问题:
    我想问问 Dan1980(也该有一些作为了)
    您所说
    =============================================================
    String s1 = new String("abc"); 
    //创建二个对象, 一个是"abc", 一个是包裹"abc"的String对象
    =============================================================
    创建的"abc"本来就是一个String对象,为什么还要创建一个  包裹"abc"的String对象我已经明白String s1 = new String("abc");肯定会创建一个对象
    我现在的理解是创建一个对象"abc",然后创建一个reference s1指向这个对象,所以我认为总共只创建了一个对象,至于您所说的 包裹"abc"的String对象 我有点不明白什么意思
      

  44.   

    to:zhangqingqi82
    一个是"abc", 一个是包裹"abc"的String对象
    =====================================
    这句话绝对的错了。这两个object根本没什么关系;更何况是 Nest.你记住,一个new 标志着一个obj的产生。即使是: new String();
      

  45.   

    哎……晕,这个也值得讨论呀,显然是2个了,所有的Java书上都有写……