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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© taotao 中级黑马   /  2013-7-31 00:19  /  1182 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 杨兴庭 于 2013-7-31 23:18 编辑

基础视频中,讲到String str1 = "abc"; String str2=new String("abc");区别的时候,老师说第二种方式产生两个对象,我很费解~百度了一下,发现众说纷纭。我现在最想知道的就是String str1 = "abc";这种方式产生的对象是在栈里?还是堆里?或者说“abc"不能称作”对象“?

{:soso_e154:}谁来告诉我,困死我了,谢谢大家

评分

参与人数 1技术分 +1 收起 理由
杜光 + 1 赞一个!

查看全部评分

7 个回复

倒序浏览
鄙人拙见认为:String str1 = "abc"; String是引用数据类型,字符串"abc"储存在堆内存的常量池中,算是一种对象吧,毕竟储存在堆内存。
希望和楼主,各位前辈高人深入探讨{:soso_e100:}
回复 使用道具 举报
String str1 = "abc";是在定义变量
String str2=new String("abc");是创建对象
String str1 = "abc"产生出来的abc存在堆内存中
回复 使用道具 举报
本帖最后由 Mr_Free 于 2013-7-31 05:08 编辑

首先我来说一下String类的特点
1.String使用private final char value[]来实现字符串的存储,也就是说String对象创建之后,就不能再修改此对象中存储的字符串内容,就是因为如此,才说String类型是不 可变的(immutable)。
  然后,你要搞清楚,什么是对象,对象,是实实在在存在的一个实体。

String str2 =new String("abc");//-------------------创建了2个对象,一个是"abc"通过""双引号创建的,他被存放在常量池里面。str2是通过new创建的对象,他被存放在堆内存中.只不过他们创建的时期不同,一个是编译期,一个是运行期!
String str1 = "abc";//---------------是先在栈中创建一个对String类的对象引用变量str,然后通过符号引用去字符串常量池里找有没有"abc",
如果没有,则将"abc"存放进字符串常量池,并令str指向”abc”,如果已经有”abc” 则直接令str指向“abc”这里面的str1是一个类类型变量,不能称为对象。

注意:str1 只是String类的引用,不能称为对象。为什么str2是对象呢,因为他被是new出来的,是在堆内存占有内存地址空间的。


然后我补充一下常量池的概念: 常量池在java用于保存在编译期已确定的,已编译的class文件中的一份数据。它包括了关于类,方法,接口等中的常量,也包括字符串常量,如String s = "java"这种申明方式;当然也可扩充,执行器产生的常量也会放入常量池,故认为常量池是JVM的一块特殊的内存空间。

评分

参与人数 1技术分 +1 收起 理由
杨兴庭 + 1

查看全部评分

回复 使用道具 举报 1 1
首先O(∩_∩)O谢谢大家!根据大家的提示,我从常量池的角度对问题进行分析,受益匪浅,下面是总结,分享一下:
假设在一个test.java文件中,包含如下类:
class Str
{
String str1 = "abc";
String str2 =new String("abc");
}
编译、加载时:
编译时,java编译器会专门用一些字节记录字符串字符值“abc",这些字节就是常量池。等到将编译好的类加载的时候,JVM会

为对应的常量池建立一个内存数据结构,并存放在  方法区  中。同时JVM会自动为字符串常量的字面值”abc”在堆中创建

String对象“abc”(intern字符串对象 ,又叫拘留字符串对象)。然后把常量池中存储“abc”的入口地址转变成这个堆中

String对象的直接地址(常量池解析)。
注意:虽然类文件中有两个“abc”,但是常量池中只有一个字面值“abc”,当然,堆中相应的“拘留字符串对象”也只有一个

,原因就不说了,我们都知道。
运行时:
当执行  String str1 = "abc";  时,因为“abc”已存在与常量池,所以,常量池中的字符串字面值“abc”  会返回与其相

对应的堆中的“拘留字符串对象-abc”的堆地址。并将地址赋值给引用str1。
当执行  String str2 =new String("abc");  用已存在的  拘留字符串对象“abc”的值  来初始化堆中用new指令创建出来

的新的String对象,引用str2实际上指向的是new出来的堆对象地址。

总结:视频中毕老师说的两个对象,一个是拘留字符串对象,另一个是用new指令创建出来的新的String对象!

评分

参与人数 1技术分 +1 收起 理由
杨兴庭 + 1 赞一个!

查看全部评分

回复 使用道具 举报
Mr_Free 发表于 2013-7-31 05:05
首先我来说一下String类的特点
1.String使用private final char value[]来实现字符串的存储,也就是说String ...

谢谢你,你对内部原理解析的最透彻。我今天也总结了一下,和你的有不同的地方,具体内容我发表在上面了,你帮我看看,是不是这样的.
回复 使用道具 举报
taotao 中级黑马 2013-7-31 20:57:36
7#
黑马李昂 发表于 2013-7-31 00:43
鄙人拙见认为:String str1 = "abc"; String是引用数据类型,字符串"abc"储存在堆内存的常量池中,算是一种 ...

谢谢参与,常量池不是放在堆内存中,是放在方法区的,具体情况我上面有发表,你看一下,对你有帮助,大家一起加油!
回复 使用道具 举报
taotao 中级黑马 2013-7-31 21:01:19
8#
xuaner0719 发表于 2013-7-31 00:47
String str1 = "abc";是在定义变量
String str2=new String("abc");是创建对象
String str1 = "abc"产生出 ...

O(∩_∩)O谢谢,帮我看看我总结的对不对,在上面~
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马