黑马程序员技术交流社区

标题: String s1=new String(“a”)内存图 总结 [打印本页]

作者: 张歆明    时间: 2013-7-23 10:06
标题: String s1=new String(“a”)内存图 总结
本帖最后由 张歆明 于 2013-7-23 13:06 编辑

这是以前别人提问的题目,我当时解答不细致,这次整理好,给有疑问的人做个参考*******************************************************************************************
1.    问题描述
1Strings1=new String ("a");
说法:new 了一个对象,"a"也是一个对象;"a"不是相当于一个参数么?为什么说"a"是个对象?
2】内存图的样子是什么?
3】分析
{1}. 由于当时看到这个问题之后,自己也不是很清楚,所以,不得不借助一下String类的参数是String的重载的构造方法
/**
* Initializesa newly created {@code String} object so that it represents
*the same sequence of characters as the argument; in other words, the
*newly created string is a copy of the argument string. Unless an
*explicit copy of {@code original} is needed, use of this constructor is
*unnecessary since Strings are immutable.
*
* @param original
*        A {@code String}
*/
public String(String original) {…}
{2}. 现在分析一下这个方法什么时候使用:
我翻译一下上面这段对这个构造方法的说明:
*************************************************************************
这个构造方法用来初始化一个和输入参数具有相同字符序列的字符串对象。换句话说,新建的这个字符串对象是传入的字符串参数对象的一份副本。除非是明确地需要使用字符串复制功能,否则由于字符串常量值是不可变的,这个构造函数是没有必要去直接使用。(意译)
*************************************************************************
【结论】:以String为参数的构造函数开发中使用可能性已经很小。所以,这个构造方法主要在考题里面出现。
2.    源码分析
(1). 分析String类的成员属性 -----源码
  1. public final class String
  2.     implements java.io.Serializable,Comparable<String>, CharSequence{
  3.     /** The value is used forcharacter storage. */
  4. private final char value[]; //存储字符串中元素的字符数组
  5. /*
  6. 注意:value是引用常量:一旦初始化指向了一个内存中的数组,
  7. 就不能再指向别的数组了
  8. */
  9.     /** The offset is the first indexof the storage that is used. */
  10.     private final int offset;    //value中存储字符串的第一个索引位置 ---常量
  11.     /** The count is the number ofcharacters in the String. */
  12.     private final int count; //value中存储字符串的长度 ---常量
  13. ...
  14. }
复制代码
【结论】这样Java实际上是使用指针(offset)计数器(count)字符数组(value[])来描述String类的
大概就是下图:一旦通过构造函数初始化这个新建的字符串之后,这个字符数组对应的指针和计数器都是固定的,不能改变了

(2). 分析String类的publicString(String original) -----源码
  1. public String(String original) {
  2.         //size表示参数数组的真实长度 ----赋值给新的变量的原因就是count是final的
  3. int size = original.count;
  4. //originalValue表示参数数组的字符数组 ----赋值给新的变量的原因就value[]
  5. //是final的
  6.         char[] originalValue = original.value;
  7.         char[] v;//临时定义的字符数组
  8.         
  9. //参数的字符数组中没有存满有效字符
  10. if (originalValue.length > size) {
  11.             int off = original.offset; //----赋值给新的变量:offset也是final的
  12.             /*
  13.                 注意Arrays的这个静态方法的返回值:
  14. a new array containing thespecified range from the original
  15. array, truncated or padded withnull characters to obtain the
  16. required length
  17.                 意思是:返回包含原数组指定范围的一个新的数组。
  18. 为了能获取(off, off + size)这个长度:
  19. 如果原数组数组不够这么长,用null字符串来填充以达到指定长度
  20. */
  21. v =Arrays.copyOfRange(originalValue, off, off + size);
  22. //v指向了新的数组
  23.         }else {//参数的字符数组中正好存满有效字符
  24.             v= originalValue;
  25.         }
  26.         this.offset = 0;
  27.         this.count = size;
  28.         this.value = v;
  29.     }
  30. }
复制代码
3.    内存图演示
(1). 回答问题1:“a”是存储在常量池的字符串
(2). 回答问题2
String s1=newString ("abc"); 通过上面的构造方法初始化之后,常量池中的" abc"和这个新在堆内存中的对象s1已经没有关系了。
(3). 内存图演示


Java中String类的模型.jpg (24.09 KB, 下载次数: 0)

Java中String类的模型

Java中String类的模型

new String内存图.jpg (123.39 KB, 下载次数: 0)

内存图演示

内存图演示

作者: admin    时间: 2013-7-23 10:50
你是一个有潜力的程序猿
作者: 张歆明    时间: 2013-7-23 10:53
admin 发表于 2013-7-23 10:50
你是一个有潜力的程序猿

谢谢管理员 我会继续努力 争取早日进黑马:)
作者: 曹奎    时间: 2013-7-23 13:40
学习了 我也会继续努力 进黑马
作者: ㄗs:/|丶hearts    时间: 2013-7-23 18:00
张歆明 发表于 2013-7-23 10:53
谢谢管理员 我会继续努力 争取早日进黑马

65技术分还没进黑马    介个是什么情况
作者: 张歆明    时间: 2013-7-23 18:08
ㄗs:/|丶hearts 发表于 2013-7-23 18:00
65技术分还没进黑马    介个是什么情况

写博客 额。。。   
作者: ㄗs:/|丶hearts    时间: 2013-7-23 18:31
张歆明 发表于 2013-7-23 18:08
写博客 额。。。

这么NB了  一下就能进入黑马了吧




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2