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.
    v = new char[size];
      System.arraycopy(originalValue, original.offset, v, 0, 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;
    }
以上是String的带参数构造方法的源代码,很容易看出来String的底层是用数组实现的。String好像是有个pool,当new一个String的时候,先看pool里面有没有,没有就在pool里面建一个,再拷贝一份到堆上,如果池里面有就直接拷贝。现在有2个问题:
   1.通过这个构造,看不出来String的pool,我该怎么才能看到,pool和堆在内存里面到底是怎么回事?   2。大家都知道,同样内容的Str,我new两次,应该是2个不同对象,但是从上面的代码来看,当执行else语句的时候, char[] originalValue = original.value;v = originalValue;this.value = v;这样每次得到的Str,它的数组还是指向了参数传进来的那个Str的数组,那得到的不是同样的对象?这里的参数是原来指向原来的Str还是对它做了一个拷贝啊?

解决方案 »

  1.   

    此回复为自动发出,仅用于显示而已,并无任何其他特殊作用
    楼主【wnba1983】截止到2008-07-24 20:16:33的历史汇总数据(不包括此帖):
    发帖的总数量:57                       发帖的总分数:1560                     每贴平均分数:27                       
    回帖的总数量:55                       得分贴总数量:5                        回帖的得分率:9%                       
    结贴的总数量:52                       结贴的总分数:1440                     
    无满意结贴数:9                        无满意结贴分:230                      
    未结的帖子数:5                        未结的总分数:120                      
    结贴的百分比:91.23 %               结分的百分比:92.31 %                  
    无满意结贴率:17.31 %               无满意结分率:15.97 %                  
    值得尊敬
      

  2.   

    只知道String是一个不可以改变的字符串 向楼主学习了
      

  3.   

    你看反编译的代码就能看到池,应该是JVM处理掉了。
    第二个问题,你也看到,这里只是对字符串内部的一个value属性引用而已,最后返回的仍然是一个新对象。
      

  4.   

    问题1:
    在int size = original.count;语句之前jvm已经处理了
    问题2:
    他们指向的char数组是相同的,但只代表他们内容相同,但是两个不同对象。
    就像两个人同名,,但他们却不是同一个人
      

  5.   

    String的pool是存在内存中的,在实际的代码中是看不到的。 数组类型属于引用传递,是把数据在内存中的地址付给变量。在你new一个字符串的时候,JVM会先去String池中寻找是否有跟你要定义的字符串相同的值,如果有,就会把这个字符串值子内存中的地址传递给你要新定义的字符串。在表面看起来是两个对象,其实引用的内存地址都是相同。
      

  6.   

    晚上刚好看了下String类的源码  可以回答下楼主的问题  呵呵
    第一个问题
    堆应该是每个程序执行时,虚拟机分配的默认大小的一片内存空间,java中内存管理的任务都叫给虚拟机了,
    所以,堆的实现,推断堆应该是和List类差不多,不够用了 ,虚拟机控制它自动增长。
    至于String类的池,应该由于java语言中对String的特殊定义(方便共享),而采取的一中策略
    字符串直接量(或者称规范化字符串,就是用引号直接引起来的)存放在字符串常量池中,这个池由
    String类负责维护。楼主所说的:
    String好像是有个pool,当new一个String的时候,先看pool里面有没有,没有就在pool里面建一个,再拷贝一份到堆上,如果池里面有就直接拷贝
    我说下我的观点
    String a = new String("abc");这种  先在字符串常量池里创建一个对象
    就是"abc" (当然  会先检查是否已经存在了值为"abc"的字符串  通过String类的Stringequals(Object obj)方法 如果有,则不再创建新的对象,直接返回已存在对象的引用;如果没有,则先创建这个对象,然后把它加入到字符串池中,再将它的引用返回。)完了根据传过来的String对象   在堆上创建一个 就是new String()
    他们引用相同的char数组  这个看String类的构造方法就可以确定  value(String类中char[]类型的字段
    保存String的值)是直接赋值的  也就是传递引用
    同时  根据构造方法  String(String orginal)也可以确定String a = new String("abc")是创建了两个对象
    楼主想详细了解的话  可以看看zangweiren的帖子
    http://topic.csdn.net/u/20080630/19/BEAB5990-FEE8-43F8-B6F4-882B4B04C89C.html 
    如果想要了解堆和字符串常量池的底层实现   推荐深入java虚拟机这本书问题二:
    char[] originalValue = original.value;v = originalValue;this.value = v;
    传进来的字符串的value属性直接赋值给新创建的字符串对象的私有属性value
    所以它们指向相同的数组对象
    但是他们是不同的字符串对象我比较好奇的是  字符串的value属性是private修饰的  怎么能够直接orignal.value引用呢
      

  7.   

    String 是建立在基本类型之上的,你所说的pool,也就是char数组,
    对于相同的字符串,String并不再新建一个,而是使用已经有的。
      

  8.   

    确实是有pool.JVM负责管理的也就是所谓的内存池.初始化一个字符串对象的时候就会先在内存池里找有没有已经存在的值相等的字符串对象,有的话就直接引用那个对象.当然如果前面如果前面也初始化过一个相同的字符串对象在内存池中,再NEW的时候这个字符串引用变量就会直接指向内存池中这个字符串常.
      

  9.   

    第2个问题里。
    虽然指向的属性名一样,但是他们分别是不同的对象的同一个属性,存储在不同的对空间中。
    虽然数组是一样的,但是字符串本身是不同的了。回10楼。
    我比较好奇的是  字符串的value属性是private修饰的  怎么能够直接orignal.value引用呢 
    可以直接饮用的。因为value虽然是private,但是value就是String 的属性。private的权限是本类内可以调用
    而现在就是在String类内调用,只不过是在另一个实例中。
    也就是说,在这个String里,封装了另一个String,虽然那个被封装的String的属性是private。但是在这里使用,也是在String类里使用阿。
      

  10.   

    private权限,不是“本对象内”而是“本类内”。:—)
      

  11.   

    不知道你们看源码的时候有没有看到这样一个方法?public native String intern();API文档的解释是:A pool of strings, initially empty, is maintained privately by the class
    所以这就是你所说的Pool,至于为什么看不到,因为这是一个native方法,不是Java来实现的,是C/C++实现的至于第二个问题,new两个相同内容的String,应该是分别有自己的count和value,count代表String有多少个characters,而value代表String的存储空间,之所以要把count和value的长度进行比较,是为了过滤掉非字符(比如空格)的String内容,而不是比较这个characters之前有没有存在