一共有3个对象,分别是: A AB ABC 在引用池里也会有3个对应的对象。 如果运行String 语句时,首先是在引用池里生成对应的对象A,AB,ABC; 如果下次运行时有相同对象的时候引用池就直接调用这个对象,如果引用池里没有此对象的话就在堆区生成一个对象 所以,首先在引用池里生成对象:A,AB,ABC;然后在堆区里生成相应的对象A,AB,ABC。
a 和 b 和c 各是一个对象 相对于String s=new String( "a ")+new String( "b ")+new String( "c "); a和b相加后ab为一个对象, ab+c又是一个对象 整个过程产生了5个对象 s指向的就是第5个对象。 其余4个没有被引用的对象会在内存紧缺的时候被垃圾回收。 ========================= 本来我也以为是这样的,看来不对啊
等 级: 发表于:2007-11-17 11:36:404楼 得分:0 a 和 b 和c 各是一个对象 相对于String s=new String( "a ")+new String( "b ")+new String( "c "); a和b相加后ab为一个对象, ab+c又是一个对象 整个过程产生了5个对象 s指向的就是第5个对象。 其余4个没有被引用的对象会在内存紧缺的时候被垃圾回收。 个人理解,如果不对楼下一定改正。
=================================================================================不知道你有没有看过Effictive Java,这书是写JDK的一牛人写的,现在跑去GOOGLE了,书中说,在写程序时,建议我们不能这样定义一个String:String s=new String( "a ") 这样不会产生两个String,当时我也纳闷,原来是这样的:“a”本身已经是一个string了,再new了一次,就产生两个了。 ================================================================================================= 对于LZ这个问题,我给你个权威的回答吧:其实编译成.class文件后string的加法是由stringbuilder/stringbuffer来连接的至于产生几个对象,当然是四个了。JDK不会傻到“a”+“b”也产生一个新对象,SUN那些大牛们难道会不知道PERFORMANCE吗。实际上,编译后可以会变成这个样子:StringBuffer ss = new StringBuffer(); ss.append("a").append("b").append("c"); String s = ss.toString;不信的话,可以去看下.CLASS文件反编译后看下。还是那句话,学东西要学精。我也在努力。
ab
abc
和引用s
四个对象.
String 类是不能被改写的.
StringBuffer可以.
相对于String s=new String("a")+new String("b")+new String("c");
a和b相加后ab为一个对象,
ab+c又是一个对象
整个过程产生了5个对象
s指向的就是第5个对象。
其余4个没有被引用的对象会在内存紧缺的时候被垃圾回收。个人理解,如果不对楼下一定改正。
b对象没有被new出来怎么和a相加呢你都说了String类是不能被改写的
如:
String a = "Hello";
System.out.println(a);StringBuffer bf = new StringBuffer("Hello");
优化后的结果:String s="abc";//声明一个String引用指向常量池中的"abc"
//单纯这一句话不会生成新的对象,执行1万次也不会产生新对象
如果不优化://常量池中有"a","b","c"三个字符串
String s="a"+"b"+"c";//产生1个临时对象"ab",及一个"abc"
对于常量池的字符串,不能认为是运行的时候才生成的,而是在编译之后就确定下来的
因此答案是0个或2个
String对象即便不写new实际上和写new效果完全等同的,因为String类太常用了,所以做了简化
to 7楼 你的好像也不对正确的应该是1个对象,编译器优化的结果
http://java.ccidnet.com/art/3539/20070912/1210357_1.html我看了这篇文章同时有做了编译试验,跟踪了jdk源码。引用
7楼 对于常量池的字符串,不能认为是运行的时候才生成的,而是在编译之后就确定下来的
"a"+"b"+"c"编译后和"abc"
完全相同
至少在程序运行时会产生一个对象,零个对象是不正确的
使用new和不使用new还是有区别的
就在池中产生了一个,引用池中的,
但String在做改变的时候实际上是将String转换为StringBuffer,而StringBuffer的操作实质上是使用char型变量,所以在下认为只有一个对象。
A
AB
ABC
在引用池里也会有3个对应的对象。
如果运行String 语句时,首先是在引用池里生成对应的对象A,AB,ABC;
如果下次运行时有相同对象的时候引用池就直接调用这个对象,如果引用池里没有此对象的话就在堆区生成一个对象
所以,首先在引用池里生成对象:A,AB,ABC;然后在堆区里生成相应的对象A,AB,ABC。
相对于String s=new String( "a ")+new String( "b ")+new String( "c ");
a和b相加后ab为一个对象,
ab+c又是一个对象
整个过程产生了5个对象
s指向的就是第5个对象。
其余4个没有被引用的对象会在内存紧缺的时候被垃圾回收。 =========================
本来我也以为是这样的,看来不对啊
String s1="a"; //这种写法,"a"会被当作常量被保存起来
String s2=new String("a"); //这种写法是创建一个String对象System.out.println(s1); //都是打出a;
System.out.println(s2);String s="a"+"b"+"c";
由是String是不可变长的,所以系统会创建一个更大的空间将a和b 存在这个空间里,之后再创建一个更大的空间把abc存起来,如果连加的太多就要用StringBuffer这个类了,写循环用这两个类分别加1000次效果就很明显了
内存中会有 a ab abc 3个字符串
"a";
"b";
"c";
"ab";
"abc".
System.out.println(s=="abc");return true, which means they are the same object in the membery.
"b ";
"c ";
"ab ";
"abc ".我不是专家,但是我这么认为,大家多支教
L0 (0)
LINENUMBER 23 L0
LDC "abcd"
ASTORE 2======================================String s2 = "a" + "b" + "c" + "d";对应的虚拟机字节码:
L1 (3)
LINENUMBER 24 L1
LDC "abcd"
ASTORE 3
没有区别。
如果pool共享池中没有"abc"标准字符串序列的对象,则在pool共享池产生一"abc"对象.引用变量s指向该对象。即产生1对象
"a",
"b"
"c"
"ab"
"abc"
s----指向"abc"的引用也算一个对象
看看这个说明吧:
哈哈,要理解这个,就要知道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个对象
我认为最后两个都是对象。s 引用变量abc 内存常量
"a","b","c","ab","abc"
还请大家多多指教!
"a","b","c","ab","abc",String声明的对象s
java 语言的的字符串常量与其它语言没什么不同, 实际上对于用了双引号括起来的字符串常量
系统会默认的为它穿件一个无名的对象
有三个引号 是3个
string s=“a”是一个对象
我不知道 string s=“a”+“b” 是两个 还是3个
要是两个的话 上面的问题 就是3个
要是3个的话 答案 就是5个希望高手指点...........
String s = "abc"编译,然后用工具反编译就知道,javap -c 也能看到
首先看这几行代码: String s ="a"+"b"+"c";
String s_ = "abc";
System.out.println(s==s_);结果为 “true”也就是说 s 和 s_ 指向了同一个对象。又因为代码中 s_ 明确的指明了其对象是 "abc" 。 所以此时应得出
String s ="a"+"b"+"c"; 应该产生至少一个对象是"abc".其次就是关于"a" ,"b" ,"c". 本人认为,内存中创建了这三个对象。可以根据 47 层的朋友留言去理解。还有就是试想CUP和内存的关系,cup是从内存中获取数据,然后运算,最后得到数据.那么在内存中如果没有"a" ,"b" ,"c"那么哪来的"abc"?
所以到这里本人认为至少已4个对象了.再有就是 s,它也是内存中开辟的一个空间,保存着对 实例 的引用.也更象一个容器.装载着某个实例(本人的愚见).它也应该算是一个对象.
到这里至少是5个了.最后,在程序运行期间是否创建了 "ab" 或是说 "bc",本人无从考证.还请高人指明. 如有错误,请楼下指出.
等 级:
发表于:2007-11-17 11:36:404楼 得分:0
a 和 b 和c 各是一个对象
相对于String s=new String( "a ")+new String( "b ")+new String( "c ");
a和b相加后ab为一个对象,
ab+c又是一个对象
整个过程产生了5个对象
s指向的就是第5个对象。
其余4个没有被引用的对象会在内存紧缺的时候被垃圾回收。 个人理解,如果不对楼下一定改正。
=================================================================================不知道你有没有看过Effictive Java,这书是写JDK的一牛人写的,现在跑去GOOGLE了,书中说,在写程序时,建议我们不能这样定义一个String:String s=new String( "a ")
这样不会产生两个String,当时我也纳闷,原来是这样的:“a”本身已经是一个string了,再new了一次,就产生两个了。
=================================================================================================
对于LZ这个问题,我给你个权威的回答吧:其实编译成.class文件后string的加法是由stringbuilder/stringbuffer来连接的至于产生几个对象,当然是四个了。JDK不会傻到“a”+“b”也产生一个新对象,SUN那些大牛们难道会不知道PERFORMANCE吗。实际上,编译后可以会变成这个样子:StringBuffer ss = new StringBuffer();
ss.append("a").append("b").append("c");
String s = ss.toString;不信的话,可以去看下.CLASS文件反编译后看下。还是那句话,学东西要学精。我也在努力。
=====================================
这里写错了,不好意思应改为:这样就会产生两个String,当时我也纳闷,原来是这样的:“a”本身已经是一个string了,再new了一次,就产生两个了。
mayandbrisa
等 级:
发表于:2007-11-20 16:10:1073楼 得分:0
至少应该是5个:
首先看这几行代码: String s = "a "+ "b "+ "c ";
String s_ = "abc ";
System.out.println(s==s_); 结果为 “true”也就是说 s 和 s_ 指向了同一个对象。又因为代码中 s_ 明确的指明了其对象是 "abc " 。 所以此时应得出
String s = "a "+ "b "+ "c "; 应该产生至少一个对象是 "abc ". 其次就是关于 "a " , "b " , "c ". 本人认为,内存中创建了这三个对象。可以根据 47 层的朋友留言去理解。还有就是试想CUP和内存的关系,cup是从内存中获取数据,然后运算,最后得到数据.那么在内存中如果没有 "a " , "b " , "c "那么哪来的 "abc "?
所以到这里本人认为至少已4个对象了. 再有就是 s,它也是内存中开辟的一个空间,保存着对 实例 的引用.也更象一个容器.装载着某个实例(本人的愚见).它也应该算是一个对象.
到这里至少是5个了. 最后,在程序运行期间是否创建了 "ab " 或是说 "bc ",本人无从考证.还请高人指明. 如有错误,请楼下指出.
=========================================================================
你的方法不对。
输入结果之所以是true,是因为jvm做了优化,考虑到性能问题,Tiger(java se 5)把最近相同的的String存储到了同一个内存,因为毕竟它是不可变的。不信的话,你可以试试下面的代码。String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2);
结果是true,大家都知道 == 是用来比较内存地址的。这说明s1, s2是同一个内存地址。
产生几个不是你想出来的,你可以去看看编译后的.CLASS文件,反编译下。
就会发现其中的奥秘了
因为String的长度是不可变得。
String s = "a" +"b" + "c";
因为String 不是基本数据类型,所以要生成对象才能使用。
先生成一个String对象"a",在生成一个String对象“b”,
执行"a"+"b"的时候,要生成一个新对象“ab",s会指向这个对象,再生成对象"c",执行"ab"+"c",
生成对象“abc",s指向这个对象,这就是这个表达是的执行过程。
所以共生成了5个对象。"a","b","ab","c","abc"
================================================================================================
Java 语言提供对字符串串联符号("+")和其他对象到字符串的转换的特殊支持。字符串串联是通过 StringBuilder(或 StringBuffer)类及其 append 方法实现的。字符串转换是通过 toString 方法实现的,该方法由 Object 类定义,并可被 Java 中所有类继承。有关字符串串联和转换的更多信息,请参阅 Gosling、Joy 和 Steele 合著的《The Java Language Specification》。
================================================================================================
有所获。
支持没有 "ab" 这个对象。
其中你给我的留言中提到:
——————————————————————————————————————————————————————————
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2);
结果是true,大家都知道 == 是用来比较内存地址的。这说明s1, s2是同一个内存地址。
——————————————————————————————————————————————————————————
本人认为正因为他们是同一个内存地址,更能证明其二者指向同一个对象。
还有你提到的四个对象应该是 "a","b","c","abc" 吧 ?
本人仍坚持 s 也为一个对象。曾经查阅过一些 c++ 的资料。其中有这样的解释。但也并非权威的资料。所以能否给出有力的论证。证明其不是一个对象。
上面有详细的说明 应该是先创建 a b c 然后再 ab abc
public static void main(String[] args){
String s="a"+"b"+"c";
}
}C:\java>javac Test.javaC:\java>javap -c Test
Compiled from "Test.java"
public class Test extends java.lang.Object{
public Test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: returnpublic static void main(java.lang.String[]);
Code:
0: ldc #2; //String abc
2: astore_1
3: return}
要了解编译器的基本行为
a b c 是一个,他们指向的s又是一个。
这怎么能混淆呢。。===================================================================其中你给我的留言中提到:
——————————————————————————————————————————————————————————
String s1 = "abc ";
String s2 = "abc ";
System.out.println(s1 == s2);
结果是true,大家都知道 == 是用来比较内存地址的。这说明s1, s2是同一个内存地址。
——————————————————————————————————————————————————————————
本人认为正因为他们是同一个内存地址,更能证明其二者指向同一个对象。
还有你提到的四个对象应该是 "a ", "b ", "c ", "abc " 吧 ?
本人仍坚持 s 也为一个对象。曾经查阅过一些 c++ 的资料。其中有这样的解释。但也并非权威的资料。所以能否给出有力的论证。证明其不是一个对象。 =========================================================================C++和JVM完全是两个东西,明白吗?String s1 = "abc ";
String s2 = "abc ";
System.out.println(s1 == s2);
之所以输出TURE,是因为JVM做了优化,STRING对象的内容是不变的,为了节省内存,把它们放到了一个内存地址里。
实际上,在JAVA SE5之前,结果输出是FALSE。这个论题其实和这里讨论的没多大关系。实际上,JAVA文件在编译成字节码之后,都会做处理,所谓的内存分配问题是装入CLASS字节码后,JVM才真正开始分配内存。
String s = "a" + "b" + "c";这样的语句会被处理成:String s = "abc"; 而如果写成:String s = new String("a") + new String("b") + new String("c");则会用StringBuilde/StringBuffer来处理了,所以,这个问题没必要再讨论了。与其在这里说这些无谓的话题,还不如去好好学学JAVA,把基础打牢。多关注下JAVA EE呢,设计方面的论题更值得研究。