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还是对它做了一个拷贝啊?
楼主【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 %
值得尊敬
第二个问题,你也看到,这里只是对字符串内部的一个value属性引用而已,最后返回的仍然是一个新对象。
在int size = original.count;语句之前jvm已经处理了
问题2:
他们指向的char数组是相同的,但只代表他们内容相同,但是两个不同对象。
就像两个人同名,,但他们却不是同一个人
第一个问题
堆应该是每个程序执行时,虚拟机分配的默认大小的一片内存空间,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引用呢
对于相同的字符串,String并不再新建一个,而是使用已经有的。
虽然指向的属性名一样,但是他们分别是不同的对象的同一个属性,存储在不同的对空间中。
虽然数组是一样的,但是字符串本身是不同的了。回10楼。
我比较好奇的是 字符串的value属性是private修饰的 怎么能够直接orignal.value引用呢
可以直接饮用的。因为value虽然是private,但是value就是String 的属性。private的权限是本类内可以调用
而现在就是在String类内调用,只不过是在另一个实例中。
也就是说,在这个String里,封装了另一个String,虽然那个被封装的String的属性是private。但是在这里使用,也是在String类里使用阿。
所以这就是你所说的Pool,至于为什么看不到,因为这是一个native方法,不是Java来实现的,是C/C++实现的至于第二个问题,new两个相同内容的String,应该是分别有自己的count和value,count代表String有多少个characters,而value代表String的存储空间,之所以要把count和value的长度进行比较,是为了过滤掉非字符(比如空格)的String内容,而不是比较这个characters之前有没有存在