String s = new String("xyz");为什么是创建2个对象呢?

解决方案 »

  1.   

    笔试的时候总考 一个是“xyz”一个是指向它的引用对象s
      

  2.   

    不一定是两个对象吧?
    public String(String original) {
    int size = original.count;
    char[] originalValue = original.value;
    char[] v;
       if (originalValue.length > size) {
          // 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.
                int off = original.offset;
                v = Arrays.copyOfRange(originalValue, off, off+size);
      } else {
          // The array representing the String is the same
          // size as the String, so no point in making a copy.
        v = originalValue;
      }
    this.offset = 0;
    this.count = size;
    this.value = v;
        }
    这是构造函数的源代码,从这里可以看到else情况下
    s和原来的"xyz"指向的是同一个对象
    String s = new String("xyz");这句话实际上是:
    1. 创建了一个字符串对象,和它的引用"xyz"
    2. 创建了一个指向这个字符串的引用s
      

  3.   

    字符串引用也算对象?不过是长度为4的int值。
      

  4.   

    两个对象,一个是“xyx”,一个是指向“xyx”的引用对象s。
      

  5.   

    这问题 我面试时候才被问过  是2个对象啦
    第一个是保存“XYZ” 第二个是保存指向"XYZ"的一个引用
      

  6.   

    就是两个对象,一个是引用变量,一个是保存“XYZ”的对象空间
      

  7.   

    yes
    两个对象
    “xyz”和 指向他的s
    顶下
      

  8.   

    String s=new String("xyz");
    s不能叫对象,它是指向对象的一个指针,在栈区占4字节。
    new String("xyz");将会在堆空间创建一个对象,"xyz"只是一个字面量,它不是对象,如果说是创建两个对象,那是因为:String内部维护一个属性char[] value;当创建String对象时自然会创建它的属性,所以会创建一个char[]对象,然后value是指向这个char[]的指针。所以,如果说是创建了两个对象,那就是一个char[]对象和一个String对象。
      

  9.   

    两个对象"xyz"是一个内建对象。说"xyz"不是对象的可以试试"xyz".xxxx,所有String的方法都可以用。new String(...)创建了第二个对象,用的是构造String(String)String s = ... 没有创建对象,只是引用了new String(...)产生的那个对象而已。
      

  10.   

    对于“创建一个对象和他的引用”这个结果——为什么这么多人都是这个答案呢?是不是哪里有所谓有标准答案?!任何一个对象都可以N多个引用,但是引用绝不是对象。引用和对象是完全分开的两个概念。StringBuffer a = new StringBuffer();
    StringBuffer b = a;
    难道这里有三个对象吗?一个StringBuffer对象和两个它的引用???简直是胡扯嘛。如果 a.append("string");
    那么 b 的 toString() 结果也会是"string",
    因为它们根本就是引用的同一个对象嘛。不说了,没可比性,引用和对象怎么可能是同一种东西。
      

  11.   

    jamesfancy(边城狂人) ( ) 信誉:116 厉害厉害!夜里出来干什么啊!我早上来的!
    ****************************************************************
    其实引用不能算作对象是C++理论,一些大师说引用是就是吧!!嘎嘎!
    其实java产生对象是以基类为基础的!StringBuffer a = new StringBuffer();
    的基类是Object,所以有基类对象产生。
    ****************************************************************
    有人给讲讲C++么?开发一直就没用过!看看C++怎么定义的!谢谢了!
    ****************************************************************
      

  12.   

    APOLLO_TS(才饮酒中水,又闻稻花香) C++和Java差不多的,只是多重继承搞得复杂。如果引用算作对象的话,那对象就多了,岂止两个String s = new String("xyz");这一句话,至少3个对象(如果引用算的话)
    RE:一些大师说引用是就是吧!!嘎嘎!
    不知道是哪位大师说的,很想认识认识这位大师……居然能把引用看作对象
      

  13.   

    如果"xyz"已经被创建过
    那么只生成了一个对象
      

  14.   

    同意 jamesfancy(边城狂人)  说的理论我想也应该是这样的大家不要说 一个引用 一个对象了
    如果 把问题该成 String s = new String("xyz"); 在堆中为什么创建了2个对象 那你怎么回答呢
      

  15.   

    大家可以查查 API 就会了解一些  侃侃STRING 的构造方法吧
      

  16.   

    String d = "xyz";
    String s = new String(d);
    System.out.println(d==s);
      

  17.   

    哈哈,要理解这个,就要知道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个对象
      

  18.   

    同意楼上的
    忽然想起好久以前看的书实际上这里隐含创建了一个string对象"xyz"
    所以应该是两个
      

  19.   

    ykzhen
    解释的好详细啊,真正受教了
      

  20.   

    ykzhen() ,赞
    我想找这篇文章来着,还没找到,呵呵。
      

  21.   

    ykzhen()
    牛人啊!
    总算理解了!
      

  22.   

    以上朋友回答有道理,但我也有自己的想法(与Class类联系,因为创建类的时候,Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。注意,所有String类型的都共享该 Class 对象!),
    String s1="test";//创建一个对象??
    String s2=new String("test");//创建2个对象??都不一定,相对而言:
    大家应该知道,String s="test";是在constant pool里面创建对象的;而String s=new String("test");是在内存堆里面创建的!如:
    1:
    public class Tets{
    public static void main(String [] args)
    {
    String s1=new String("test");//创建2个对象/*如果你的程序只有这么一段程序的话,那么首先先由Java 虚拟机及通过调用类加载器中的 defineClass 方法自动构造Class对象,因为在String s1=new String("test");之前并没有创建任何String类型的对象,所以先是Java 虚拟机及通过调用类加载器中的 defineClass 方法自动构造Class对象!这个是第一个对象,还有new String("test")在堆里面创建的一个,一共2个,假如,(String s1=new String("test");)它前面有代码并且创建过String类的实例,那么可以说:String s1=new String("test");这句代码,它只创建一个在对象,就是new出来的这个对象*/
    }  
    }
    2:public class Tets{
    public static void main(String [] args)
    {
    String s1="test";//创建2个对象
    /*
    同理,只有它一条代码,需要创建Class对象,并且把"test"对象放在pool中,一共产生 2个对象,一个是Class和在pool中的"test"对象,假如它前面的有代码并且创建过String类的实例,道理同上,没必要再重复,
    */
    }  
    }
    一个例子:
    public class Test
    {
    public static void main(String [] args)
    {
    String s1=new String("test");//创建2个对象,一个Class和一个堆里面
    String s2="test";//创建1个对象,s2指向pool里面的"test"对象
    String s3="test";//创建0个对象,指向s2指想pool里面的那个对象
    String s4=s2;//创建0个对象,指向s2,s3指想pool里面的那个对象
    String s5=new String("test");//创建1个对象在堆里面,注意,与s1没关系System.out.println(s2=="test");//true s2=="test"很明显true
    System.out.println(s2==s3);//true,因为指向的都是pool里面的那个"test"
    System.out.println(s2==s4);//true,同上,那么s3和s4...:)
    System.out.println(s1==s5);//false,很明显,false
    System.out.println(s1==s2);//false,指向的对象不一样,下面再说
    System.out.println(s1=="test");//false,难道s1!="tset"?下面再说System.out.println("---------------");s1=s2;
    System.out.println(s1=="test");//true,下面说
    }
    }
    说明:1,System.out.println(s1==s2);很明显,s2指向的对象"test"是在pool里面,而s1指向的是堆里面的"test"对象(s1指向的内存区),所以返回false.
    2,System.out.println(s1=="test");s1指向的是堆里面的"test"对象(s1指向的内存区),而"test"是程序刚刚建立的(其实是共用pool里面的那个已经创建了的"test"对象,也就是我们s2="test"时候,在pool里面创建的),所以s1指向的堆里的"test"对象
    和"test"(pool里面)并不是一样个对象,所以返回false.
    3,当我们s1=s2;的时候,很明显,把s2的指给了s1,s1指向pool里面的"test",这个时候,s2也指向了pool里面的"test"对象了,当System.out.println(s1=="test");时候,java虚拟机创建"test"对象,注意,其实没创建,和前面讲的一样,公用s1="test"创建的"test"对象(pool里面的),所以,s1=="test"(pool里面的),同样,s1=s2=s3=s4!而为什么在网上都说String s=new String("test");创建了2个对象?那可能因为它就写这么一句代码,误让人默认的认为执行代码之前并不实例任何一个String对象过(也许很多人不会这么想,),跟着别人或者不经思考的就说2个,斟是说存放在栈内存中专门存放String对象引用的s变量是一个对象!实在不可原谅!是于我的理解是否正确,也并不重要了,必竟我也写出了我想法了,再说了,我只是3流大学,不,是N流学校的学生罢了,再说了,我又不是SUN公司的头头,连个职工都不粘边,靠!
    罗里罗嗦的说了一下,好了,大家应该明白我的意思了.
      

  23.   

    我想指出的是:
    anicetomas的代码解释这里有点错误:String s1=new String("test");//创建2个对象,一个Class和一个堆里面
    String s2="test";//创建1个对象,s2指向pool里面的"test"对象s1创建的时候,既在string pool里面创建了string对象,也在内存上(非string池里)创建了string对象.
    所以到了String s2="test" 应该是没有创建任何对象,而是引用了由s1在string pool内创建的对象.
      

  24.   

    就拿F29这个来说
    String   s= "Hello "; 
    s= "Java "; 
    String   s1= "Hello "; 
    String   s2=new   String( "Hello "); "Hello "已经被创建了
    String   s2=new   String( "Hello ");则只创建了一个
    所以我觉得题目本身就问得有问题
      

  25.   

    TO 39楼。
    偶尔回头看自己的帖子,、感觉自己真大意。
    是的,那个地方有错误,应该没有创建对象,它和s3是一样的道理,呵呵。
      

  26.   

    是两个对象,但不是N多人所说的一个对象和一个指向该对象的引用,引用并不是对象。在创建一个String s = new String("java");的时候,JVM会到constant pool也就是常量池中去检查看是否有一个"java"对象了,如果没有则在常量池中创建一个。之后会在堆内存中分配了一个空间,放置这个new出来的String对象,形式如下:java.lang.String@123b,@后面的数字就是该对象的HashCode。常量池是在编译期生成的,而new一个对象是在运行时进行的,有一个先后顺序。
      

  27.   

    总的来说String池中存在“xyz“,就创建一个对象,不存在,则两个。
    这个讲的很好