A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© flowerdance 中级黑马   /  2015-4-22 21:44  /  741 人查看  /  12 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

大家好 最近喜欢研究String类型 所以和大家分享学习String等基本类型的心得
5. 关于String str = "abc"的内部工作。Java内部将此语句转化为以下几个步骤:
(1)先定义一个名为str的对String类的对象引用变量:String str;
(2) 在栈中查找有没有存放值为"abc"的地址,如果没有,则开辟一个存放字面值为"abc"的地址,接着创建一个新的String类的对象o,并将o的字符 串值指向这个地址,而且在栈中这个地址旁边记下这个引用的对象o。如果已经有了值为"abc"的地址,则查找对象o,并返回o的地址。
(3)将str指向对象o的地址。
值得注意的是,一般String类中字符串值都是直接存值的。但像String str = "abc";这种场合下,其字符串值却是保存了一个指向存在栈中数据的引用!
为了更好地说明这个问题,我们可以通过以下的几个代码进行验证。
  String str1 = "abc";
  String str2 = "abc";
  System.out.println(str1==str2);  //true
注意,我们这里并不用str1.equals(str2);的方式,因为这将比较两个字符串的值是否相等。==号,根据JDK的说明,只有在两个引用都指向了同一个对象时才返回真值。而我们在这里要看的是,str1与str2是否都指向了同一个对象。
结果说明,JVM创建了两个引用str1和str2,但只创建了一个对象,而且两个引用都指向了这个对象。
我们再来更进一步,将以上代码改成:
  String str1 = "abc";
  String str2 = "abc";
  str1 = "bcd";
  System.out.println(str1 + "," + str2);  //bcd, abc
  System.out.println(str1==str2);  //false
这就是说,赋值的变化导致了类对象引用的变化,str1指向了另外一个新对象!而str2仍旧指向原来的对象。上例中,当我们将str1的值改为"bcd"时,JVM发现在栈中没有存放该值的地址,便开辟了这个地址,并创建了一个新的对象,其字符串的值指向这个地址。
事 实上,String类被设计成为不可改变(immutable)的类。如果你要改变其值,可以,但JVM在运行时根据新值悄悄创建了一个新对象,然后将这 个对象的地址返回给原来类的引用。这个创建过程虽说是完全自动进行的,但它毕竟占用了更多的时间。在对时间要求比较敏感的环境中,会带有一定的不良影响。
再修改原来代码:
  String str1 = "abc";
  String str2 = "abc";
  
  str1 = "bcd";
  
  String str3 = str1;
  System.out.println(str3);  //bcd

  String str4 = "bcd";
  System.out.println(str1 == str4);  //true   
str3这个对象的引用直接指向str1所指向的对象(注意,str3并没有创建新对象)。当str1改完其值后,再创建一个String的引用str4,并指向因str1修改值而创建的新的对象。可以发现,这回str4也没有创建新的对象,从而再次实现栈中数据的共享。
我们再接着看以下的代码。
  String str1 = new [t1] String("abc");
  String str2 = "abc";
  System.out.println(str1==str2);  //false
创建了两个引用。创建了两个对象。两个引用分别指向不同的两个对象。
  String str1 = "abc";
  String str2 = new String("abc");
  System.out.println(str1==str2);  //false
创建了两个引用。创建了两个对象。两个引用分别指向不同的两个对象。
以上两段代码说明,只要是用new()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即使与栈中的数据相同,也不会与栈中的数据共享。
6. 数据类型包装类的值不可修改。不仅仅是String类的值不可修改,所有的数据类型包装类都不能更改其内部的值。

12 个回复

倒序浏览
赞 感谢分享     
回复 使用道具 举报
这个类型很特殊也很常用,老师说了必须掌握的!总结的还行,举例也很详细!
回复 使用道具 举报
不错,学习了
回复 使用道具 举报
感谢你的分享啊,很有用的
回复 使用道具 举报
挺全的,挺有用。
回复 使用道具 举报
感谢 分享
回复 使用道具 举报
谢谢分享
回复 使用道具 举报
我觉得字符串是在常量池以查表形式生成的地址指向,因其是以查表法的方式生成的地址指向,因此是不可改变的;栈内存是以{}区分空间的,因此在栈内存生成的变量会因{}的平级或嵌套等逻辑划分不同而有不同的作用域,也就会出现同名变量指向相同对象的地址引用的情况,这种情况在多态方法应用中形参与实参变量名相同时,应该会碰到。
回复 使用道具 举报
wyw 中级黑马 2015-4-22 23:47:53
10#
笔记够详细,赞个!
回复 使用道具 举报
很详细,谢谢分享
回复 使用道具 举报
复习~闪人
回复 使用道具 举报
Oh.Ba 中级黑马 2015-4-23 00:22:30
13#
好深奥,弄不明白
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马