关于String a = new String("b") 的精确解析 (精)

bxdg42578670 2008-01-07 04:18:08

String a = new String("b"); 到底是几个对象呢?

我的答案: 只有一个对象!

帖子中回答两个的居多; 而且在baidu google上搜索居然也是回答两个的居多!
大部分认为: 一个是new String()出来的; 一个是"b";


我学java以来,不断的提醒自己 对象是new new new new !~ 不new 哪里来的对象呢?.

我将自己的观点剖析给大家, 如果我的观点错误了,请大家给予反驳:

很多人认为"b";是一个对象; 那要从String 这个类说起了!~

String 是个引用类型, 引用类型是以对象的形式存在;这句话确实不假!
可是大家已经发现了 new String () 和"b" 没有放在同一个位置; 一个放在堆中; 一个放在池中!
大家认为正常吗?. 对象是可以随便放的吗?. 说到这里可能有人反驳:那又怎么样!~ 以后还要把对象放在栈中!
(有人反驳观点的时候竟然把基础数据类型也当成对象来说!详在后面!)
这样一来, 大家乱放,我们怎么控制其位置啊?.

我们要看清楚String池; 它是一个固定的!~ 我们可以从里面取值; 却无法改变它!如果你说那里面的全是对象,
那我倒想问问那里面有多少对象?. 难道要说不计其数的对象?.说到这里可能有人会说:你的抽象思维有待提高啊!

有String池 是不是还有Integer池 是不是还有Boolean池 等等;; 我不信它把对象一个一个都给你创建好了?.

创建对象---就是用java提供的new关键字为对象分配存储空间; 这样的对象全部都在heap中; 这样的对象才可以称得为java中的对象;

而字符串常量是放在dataSegment中; 方法体也放在这里; 为什么非要将一个字符串常量规定说明为一个对象呢?. 既然是那样!
那还规定常量做什么?. 规定变量做什么?. 人们大肆想象!~ 甚至我可以说对象是个永远不存在的东西算了!~我们在面临逻辑思维思考时是有条件的!~难道你没有学过离散数学的命题逻辑吗?. 在一定的条件下进行推理!

说到这里,先将有人将基础数据类型想象成对象的问题说明一下:
他的反驳观点是这样的:

Object o = 5;//可行

5,是一个int类型的常量 却变成了一个Object对象; 难道你不认为这个int类型常量也是一个对象吗?.


基础数据类型更不可能成为一个对象了!~ 不信你去instanceof一下!~
一个是引用类型; 一个是基础数据类型; 连类型都不相同; 怎么可能会是一个对象?.
说到这里有人可能疑惑了; 那上面可行啊!~你这不是胡说吗?. 那要看它里面的运行过程了!~
我们都知道java将基础数据类型全都给了包装类!目的就是为了实现基础数据类型与引用类型之间的交换!

说到交换, 大家看下面的一组例子:

int i1 = 5;
Object o = 5;
Integer i2 = 5;
Integer i3 = new Integer(5);
Integer i4 = new Integer(5);

i1 == i2; i1 == i3; i1 == i4; i1 == o; i2 == o;//true
i2 != i3 i3 != i4 o != i4;//true


从上面可以看出 o已经变成了一个Integer类型的 Object类型 对象;
这里全是引用类型!~ Integer 不是基础类型, 而是引用类型;
但是5只是一个int类型的常量, 不管你声明的是什么?...


...全文
1338 73 打赏 收藏 转发到动态 举报
写回复
用AI写文章
73 条回复
切换为时间正序
请发表友善的回复…
发表回复
suisui1990523 2011-08-25
  • 打赏
  • 举报
回复
算了吧!我们去问问那个创建这个语言的人吧!
lgh1117 2010-07-21
  • 打赏
  • 举报
回复
经典,大家把java的自字符串的产生剖析得淋漓尽致
lliiqiang 2009-03-28
  • 打赏
  • 举报
回复
其实楼主说的有一定道理:
String a = new String("b");
这句话是包含了两个字符串,而不是创建了两个字符串。
因为字符串"b"是编译的时候就已经创建了,运行这句话的时候只是调用这个字符串"b"而已,实际上这句话只是创建了一个字符串,而"b"是编译的时候创建的,而不是运行这句话的时候创建的,有点咬文嚼字的嫌疑
另外说明一下1+2+"ab"编译是通不过的,只能是""+(1+2)+"ab",即只能是字符串加别的,不能别的加字符串而且是从左到右,变成了字符串
lliiqiang 2009-03-28
  • 打赏
  • 举报
回复
new String("b").里面的"b"是String类型参数,new String("b").是以"b"为基础创建的新的字符串,每次new 都要创建一个新的对象
new String(new String("b")).一共是几个字符串?
arlylee 2009-03-01
  • 打赏
  • 举报
回复
我也在思索这个问题,不得其解.
lliiqiang 2008-12-15
  • 打赏
  • 举报
回复
是两个对象,一个是编译时,在字符串常量连接池中创建的"b"对象,一个是运行时根据字符串常量连接池中创建的"b"对象为模板创建的new String("b");对象

理由,利用字符串的扣留机制测试一下下面的代码:

String m="a";
String n="b";
String p=new String("ab");
String q="ab";
q=q.intern();
System.out.println(q==p);
System.out.println(q=="ab");

结果是
false
true
说明创建字符串new String("ab")之前已经先创建了字符串对象"ab"
Y125348369 2008-09-22
  • 打赏
  • 举报
回复
顶顶
多谢各位高手了 学习中....
gks_cn 2008-06-26
  • 打赏
  • 举报
回复
好热闹
ilrxx 2008-06-25
  • 打赏
  • 举报
回复
不管有几个对象,我觉得lz没有搞清楚一个问题就是
==比较的是内存地址,而equals比较的才是内容,你上面自己举的例子可以推翻了......

另:如果公司问这种问题,我答对也不会去..
as098 2008-06-25
  • 打赏
  • 举报
回复

String s1 = "abc";
String s2 = "abc" + s1 ;
String s3 = "abcabc";


s1被赋予的"abc"在String池中

根据上面高手所说,在给s2赋值的时候发生了
StringBuffer s_buffer_1 = new StringBuffer( new String("abc") );
StringBuffer s_buffer_abc = new StringBuffer( new String("abc") );
StringBuffer s_buffer = s_buffer_1 + s_buffer_abc;
String s2 = s_buffer.toString();

s2指向了内存中的"abcabc",s3指向了String池中的"abcabc",所以不等


本来没想明白,等写完回帖明白了,回帖果然是好习惯啊
quailman 2008-06-25
  • 打赏
  • 举报
回复
好激烈
wangshizhu79 2008-06-25
  • 打赏
  • 举报
回复
[Quote=引用 56 楼 ykzhen 的回复:]
好现在我们看题目:
String s = new String( "xyz ");
首先在string池内找,找到?不创建string对象,否则创建, 这样就一个string对象
遇到new运算符号了,在内存上创建string对象,并将其返回给s,又一个对象

所以总共是2个对象
[/Quote]

看了大家的回复,我学到了不少东西
这里提出一点自己的见解

String s = new String( "xyz ");

按照56楼的说法,如果找不到就新建一个,这时产生2个对象
如果找到了,就只创建一个对象,但是xyz既然在池中,
就说明必然有一个对象是因它而创建,但不是这段代码所创建
所以说2个对象是对的
但有一个不一定是这段代码所创建
jing61281125 2008-06-25
  • 打赏
  • 举报
回复
楼主好精神。值得敬佩。
我刚刚搞明白new string 的问题。觉得是2个对象。。没想到又看到楼主的帖子。我和楼主一起入魔!!!
龙宝3000 2008-06-25
  • 打赏
  • 举报
回复
学习一哈
Sou2012 2008-06-25
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 mcluvin 的回复:]
晕,咋越搞越复杂了呢。

String s = 1 + 2 + new String("abc");

先执行算术运算1+2=3,再用StringBuffer连接字符串并返回一个新的String对象给s。

一个在堆上,一个在String池里,比较“==”肯定返回false了。

楼上的貌似也跟着走火入魔了~~~
[/Quote]
  • 打赏
  • 举报
回复
string pool看过没
ykzhen 2008-06-23
  • 打赏
  • 举报
回复
我以前在
http://topic.csdn.net/u/20070828/10/43260254-04f1-4ac0-9da1-b48af45c2a83.html?1646266974
回答过这个问题。(29楼)


哈哈,要理解这个,就要知道string类的工作原理。

你知道在java中除了8中基本类型外,其他的都是类对象以及其引用。所以 "xyz "在java中它是一个String对象.对于string类对象来说他的对象值是不能修改的,也就是具有不变性。


看:
String s= "Hello ";
s= "Java ";
String s1= "Hello ";
String s2=new String( "Hello ");

啊,s所引用的string对象不是被修改了吗?之前所说的不变性,去那里了啊?

你别着急,让我告诉你说发生了什么事情:
在jvm的工作过程中,会创建一片的内存空间专门存入string对象。我们把这片内存空间叫做string池。

String s= "Hello ";当jvm看到 "Hello ",在string池创建string对象存储它,并将他的引用返回给s。
s= "Java ",当jvm看到 "Java ",在string池创建新的string对象存储它,再把新建的string对象的引用返回给s。而原先的 "Hello "仍然在string池内。没有消失,他是不能被修改的。

所以我们仅仅是改变了s的引用,而没有改变他所引用的对象,因为string对象的值是不能被修改的。

String s1= "Hello ";jvm首先在string池内里面看找不找到字符串 "Hello ",找到,返回他的引用给s1,否则,创建新的string对象,放到string池里。这里由于s= "Hello "了,对象已经被引用,所以依据规则s和s1都是引用同一个对象。所以 s==s1将返回true。(==,对于非基本类型,是比较两引用是否引用内存中的同一个对象)

String s2=String( "Hello ");jvm首先在string池内里面看找不找到字符串 "Hello ",找到,不做任何事情,否则,创建新的string对象,放到string池里面。由于遇到了new,还会在内存上(不是string池里面)创建 string对象存储 "Hello ",并将内存上的(不是string池内的)string对象返回给s2。所以s==s2将返回false,不是引用同一个对象。

好现在我们看题目:
String s = new String( "xyz ");
首先在string池内找,找到?不创建string对象,否则创建, 这样就一个string对象
遇到new运算符号了,在内存上创建string对象,并将其返回给s,又一个对象

所以总共是2个对象
isk_java 2008-01-10
  • 打赏
  • 举报
回复
这种面试题怎么回答才好了呢?。。。学习中
toesboy 2008-01-08
  • 打赏
  • 举报
回复


to 楼主:

对象不一定是new才出来的

说对象只有new才能出来,那纯粹扯淡

相信书,但不要迷信书------孙鑫
yuki67580345 2008-01-08
  • 打赏
  • 举报
回复
String s="b";
String s= new String("b"); new 出一个对象、
加载更多回复(52)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧