为什么e和c指向的不是同一个对象??请高手做出解释,谢谢。。

问题描述

publicclassStringTest{publicstaticvoidmain(String[]args){Stringa=“ab”;System.out.println(”Stringa=“ab”;”);Stringb=“cd”;System.out.println(”Stringb=“cd”;”);Stringc=“abcd”;Stringd=“ab”+“cd”;if(d==c){System.out.println(”"ab”+”cd”创建的对象“加入了”字符串池中”);}else{System.out.println(”"ab”+”cd”创建的对象“没加入”字符串池中”);}Stringe=a+“cd”;if(e==c){System.out.println(”a+”cd”创建的对象“加入了”字符串池中”);}else{System.out.println(”a+”cd”创建的对象“没加入”字符串池中”);}}}为什么e和c指向的不是同一个对象??请高手做出解释,谢谢。。

解决方案

解决方案二:
如果Stringe="ab"+"cd";那么就是一个对象了,你这样不是

解决方案三:
因为"ab"+"cd"编译器知道它一定是常量"abcd",所以编译过程中就把它直接当作"abcd"了。而a+"cd"由于编译器不知道a这个变量里面是什么东西,所以这个值是运行的时候算出来的,所以是一个新的String。
解决方案四:
这个东西书上讲的很清楚c和e指向两个不同的内存单元他们是不可能等的两个变量的内存单元相等的概率极低的估计你想要判断他们是不是一个类如果你要判断他们是不是一个类那么不能用等号
解决方案五:
要想让他们相等就给e=c这样e就引用了c的地址
解决方案六:
2楼正解。
解决方案七:
对2楼的一点补充:1.通过常量表达式计算的String,计算在编译时进行,并将它作为String字面常量对待。2.通过连接操作得到的String(非常量表达式),连接操作是运行时进行的,会新创建对象,所以它们是不同的。
解决方案八:
因为当编译器运行Stringa=“ab”;时编译器在内存数据空间(就是字符串池)中分配了一个空间,值为“ab”,而在栈内存空间中分配了一个空间,名字叫做a,它的值为地址指向了数据空间的“ab”,(虽然java中没有指针,但实际上java里处处有指针,上面明显就是一个指针的应用)。同理Stringb=“cd”;Stringc=“abcd”;都在数据空间分配了空间“cd”空间“abcd”,而在栈内存中分配了空间b指向“cd”,空间c指向“abcd”语句Stringd=“ab”+“cd”;以为“ab”+“cd”是字符串相加,相当于“abcd”;这个时候编译器有个优化,并没有在数据空间分配一个新的内存来存放“abcd”,以为它发现已经有个“abcd”存在,所以他把存在的“abcd”的地址赋值给在栈内存空间新分配的空间d,当做if(d==c)时,d和c里存放的都是数据空间中“abcd”的地址,所以d等于c,if判断成立容器内我们再来看看Stringe=a+“cd”;语句编译器是如何编译的首先一样在栈内存空间中分配了一个新的空间e,而a+“cd”编译器编译时,a为一个引用(因为a为一个变量,这里引用了这个变量),在java中,所用的引用都会在堆内存空间中分配一个空间,所以此时在堆内存空间中开辟了一个空间,这个空间存放了a的值(就是数据空间中“ab”的地址)和数据空间中“cd”的地址,而此时在栈空间中e的值为a+“cd”在堆空间得地址,此时在做if(e==c)e为a+“cd”在堆空间得地址,c为“abcd”在数据空间中的地址结果明显是不相等的!如果此时要得到if(e==c)为true,需要用到函数equalsif()方法。
解决方案九:
呵呵上面有不少地方打错了咳为什么在这个论坛不能对自己发出的帖子进行重新编译呢?因为当编译器运行Stringa=“ab”;时编译器在内存数据空间(就是字符串池)中分配了一个空间,值为“ab”,而在栈内存空间中分配了一个空间,名字叫做a,它的值为一个地址指向了数据空间的“ab”,(虽然java中没有指针,但实际上java里处处有指针,上面明显就是一个指针的应用)。同理Stringb=“cd”;Stringc=“abcd”;都在数据空间分配了空间“cd”空间“abcd”,而在栈内存中分配了空间b指向“cd”,空间c指向“abcd”语句Stringd=“ab”+“cd”;因为“ab”+“cd”是字符串相加,相当于“abcd”;这个时候编译器有个优化,并没有在数据空间分配一个新的内存空间来存放“abcd”,因为它发现已经有个“abcd”存在,所以它把存在的“abcd”的地址赋值给在栈内存空间新分配的空间d,当做if(d==c)时,d和c里存放的都是数据空间中“abcd”的地址,所以d等于c,if判断成立让我们再来看看Stringe=a+“cd”;语句,编译器是如何编译的首先一样在栈内存空间中分配了一个新的空间e,而a+“cd”编译器编译时,a为一个引用(因为a为一个变量,这里引用了这个变量),在java中,所用的引用都会在堆内存空间中分配一个空间,所以此时在堆内存空间中开辟了一个空间,这个空间存放了a的值(就是数据空间中“ab”的地址)和数据空间中“cd”的地址,而此时在栈空间中e的值为a+“cd”在堆空间得地址,此时在做if(e==c)e为a+“cd”在堆空间得地址,c为“abcd”在数据空间中的地址结果明显是不相等的!如果此时要得到if(e==c)为true,需要用到函数equals()方法。
解决方案十:
字面常量相加在编译器就确定了,所以放在常量池了后者的一个对象和一个字面常量相加发生在运行期,而且是StringBuilder.toString()的结果,这个对象放在栈里面了
解决方案十一:
路过学习
解决方案十二:
引用7楼csliyu的回复:

因为当编译器运行Stringa=“ab”;时编译器在内存数据空间(就是字符串池)中分配了一个空间,值为“ab”,而在栈内存空间中分配了一个空间,名字叫做a,它的值为地址指向了数据空间的“ab”,(虽然java中没有指针,但实际上java里处处有指针,上面明显就是一个指针的应用)。同理Stringb=“cd”;Stringc=“abcd”;都在数据空间分配了空间“cd”空间“abcd”,而在栈内存中分配了空间b指向“cd”,空间c指向“abcd”语句Stringd=“ab”+“cd”;以为“ab”+“cd”是字符串相加,相当于“abcd”;这个时候编译器有个优化,并没有在数据空间分配一个新的内存来存放“abcd”,以为它发现已经有个“abcd”存在,所以他把存在的“abcd”的地址赋值给在栈内存空间新分配的空间d,当做if(d==c)时,d和c里存放的都是数据空间中“abcd”的地址,所以d等于c,if判断成立容器内我们再来看看Stringe=a+“cd”;语句编译器是如何编译的首先一样在栈内存空间中分配了一个新的空间e,而a+“cd”编译器编译时,a为一个引用(因为a为一个变量,这里引用了这个变量),在java中,所用的引用都会在堆内存空间中分配一个空间,所以此时在堆内存空间中开辟了一个空间,这个空间存放了a的值(就是数据空间中“ab”的地址)和数据空间中“cd”的地址,而此时在栈空间中e的值为a+“cd”在堆空间得地址,此时在做if(e==c)e为a+“cd”在堆空间得地址,c为“abcd”在数据空间中的地址结果明显是不相等的!如果此时要得到if(e==c)为true,需要用到函数equalsif()方法。

相当的完整
解决方案十三:
e.equal(c)=true
解决方案十四:
七楼的,我有点不明白,你的a一会指向数据空间,一会指向堆,什么意思啊?
解决方案十五:
因为当编译器运行Stringa=“ab”;时编译器在内存数据空间(就是字符串池)中分配了一个空间,值为“ab”,而在栈内存空间中分配了一个空间,名字叫做a,它的值为地址指向了数据空间的“ab”,a为一个引用(因为a为一个变量,这里引用了这个变量),在java中,所用的引用都会在堆内存空间中分配一个空间,所以此时在堆内存空间中开辟了一个空间,这个空间存放了a的值不矛盾吗?
解决方案:
引用2楼zrcvic的回复:

因为 "ab" + "cd" 编译器知道它一定是常量 "abcd",所以编译过程中就把它直接当作 "abcd" 了。而 a + "cd" 由于编译器不知道 a 这个变量里面是什么东西,所以这个值是运行的时候算出来的,所以是一个新的 String。

正解
解决方案:
正好有此疑问,收藏了。
解决方案:
引用14楼kangbaoxing的回复:

因为当编译器运行Stringa=“ab”;时编译器在内存数据空间(就是字符串池)中分配了一个空间,值为“ab”,而在栈内存空间中分配了一个空间,名字叫做a,它的值为地址指向了数据空间的“ab”,a为一个引用(因为a为一个变量,这里引用了这个变量),在java中,所用的引用都会在堆内存空间中分配一个空间,所以此时在堆内存空间中开辟了一个空间,这个空间存放了a的值不矛盾吗?

是e指向堆内存应为是e引用了a,我说的是a为一个引用并不是a指向堆内存而此时在栈空间中e的值为a+“cd”在堆空间得地址说明e指向这个新分配的内存空间这个空间存放了a的值说的是新开辟的内存空间存放了a的值,就是新开辟的内存空间指向数据空间中的“ab”,实际上在堆内存中的这个内存空间里有分割成两个空间,一个指向数据空间中的“ab”,另指向数据空间中的“cd”
解决方案:
如果是初学者,建议别在这上面纠缠,学三个月,自然清楚了。
解决方案:
讨论这么多有什么用?这完全取决于编译器的行为。你可以反编译一下看一下javac做了些什么?Stringa="ab";Stringb="cd";Stringc="abcd";Stringd="abcd";Stringe=(newStringBuilder(String.valueOf(a))).append("cd").toString();这是我看到的。你觉得不爽可以自己写个智能编译器,把e也解释成"abcd",不过这可能和java规范有冲突。^^
解决方案:
去理解一下字符串对象吧,还有就是equals()和==的区别,最好了解一下内存分配
解决方案:
晕死我了,原来是Java
解决方案:
//DecompiledbyDJv3.7.7.81Copyright2004AtanasNeshkovDate:2009-10-1817:32:02//HomePage:http://members.fortunecity.com/neshkov/dj.html-Checkoftenfornewversion!//Decompileroptions:packimports(3)//SourceFileName:Test.javaimportjava.io.PrintStream;publicclassStringTest{publicStringTest(){}publicstaticvoidmain(Stringargs[]){Strings="ab";System.out.println("Stringa="ab";");Strings1="cd";System.out.println("Stringb="cd";");Strings2="abcd";Strings3="abcd";if(s3==s2)System.out.println(""ab"+"cd"u521Bu5EFAu7684u5BF9u8C61"u52A0u5165u4E86"u5B57u7B26u4E32u6C60u4E2D");elseSystem.out.println(""ab"+"cd"u521Bu5EFAu7684u5BF9u8C61"u6CA1u52A0u5165"u5B57u7B26u4E32u6C60u4E2D");Strings4=(newStringBuilder()).append(s).append("cd").toString();if(s4==s2)System.out.println("a+"cd"u521Bu5EFAu7684u5BF9u8C61"u52A0u5165u4E86"u5B57u7B26u4E32u6C60u4E2D");elseSystem.out.println("a+"cd"u521Bu5EFAu7684u5BF9u8C61"u6CA1u52A0u5165"u5B57u7B26u4E32u6C60u4E2D");}}

我什么都不想说,贴出源代码大家都好看!
解决方案:
ding...............

时间: 2024-10-31 08:42:52

为什么e和c指向的不是同一个对象??请高手做出解释,谢谢。。的相关文章

c++的问题-关于类的成员变量指向在堆上的对象的选择:指针/auto_ptr<>/shared_ptr<> ?

问题描述 关于类的成员变量指向在堆上的对象的选择:指针/auto_ptr<>/shared_ptr<> ? 在堆上的对象作为一个类的一个成员变量,我了解到的至少有三种方式(如下所示): class A{ } class B{ A* m_pA1; auto_ptrm_pA2: shared_ptrm_pA3: } B::B():m_pA1(new A)m_pA2(auto_ptr(new A))m_pA3(shared_ptr(new A)){ } 针对这三种方案,在什么情况下选择哪

.NET (C#) Internals: Struct and Class

引言 Struct与Class的异同?本是一个老生常谈话题,前几天看帖就看到了Struct 与Class辨析,其中也提到了<[你必须知道的.NET] 第四回:后来居上:class和struct>(虽然在园子里看了这个系列,但仍然买了本书看),回帖也特别热闹.我也躺下这个浑水!希望能给您带来不一样的视觉,欢迎评论.本文主题如下: 直观印象 深入分析  刨根问底(刨祖坟) 特别之处ReadOnly 浅出 一.直观印象 Struct与Class的异同,到底什么是什么呢?首先来两段代码,给个直观印象.

JavaScript数组所有API全解密

全文共13k+字,系统讲解了JavaScript数组的各种特性和API. 数组是一种非常重要的数据类型,它语法简单.灵活.高效. 在多数编程语言中,数组都充当着至关重要的角色,以至于很难想象没有数组的编程语言会是什么模样.特别是JavaScript,它天生的灵活性,又进一步发挥了数组的特长,丰富了数组的使用场景.可以豪不夸张地说,不深入地了解数组,不足以写JavaScript. 截止ES7规范,数组共包含33个标准的API方法和一个非标准的API方法,使用场景和使用方案纷繁复杂,其中有不少浅坑.

译文---C#堆VS栈(Part One)

原文:译文---C#堆VS栈(Part One) 前言 本文主要是讲解C#语言在内存中堆.栈的使用情况,使读者能更好的理解值类型.引用类型以及线程栈.托管堆.       首先感谢原文作者:Matthew Cochran 为我们带来了一篇非常好的文章,并配以大量图示,帮助我们更好的理解堆栈之间的调用,本文是在作者原文的基础上进行内容上的精简以及加入我个人在这方面的理解和注释.       最后要感谢博客园的田志良,当我搜索堆栈内部使用时,搜索到了作者的文章,吸取了大量有用的知识,而且翻译的也非常

java-基础-String、StringBuilder以及StringBuffer剖析

String源码分析 从一段代码说起: public void stringTest(){ String a = "a"+"b"+1; String b = "ab1"; System.out.println(a == b); } 大家猜一猜结果如何?如果你的结论是true.好吧,再来一段代码: public void stringTest(){ String a = new String("ab1"); String b =

synchronized关键字不能被继承的问题

问题描述 我发现许多地方提及synchronized的关键字不能被继承,但是通过实验发现synchronized的关键字是能够被继承的,是我的实验方式不对?请高手指教,谢谢importjava.text.SimpleDateFormat;importjava.util.Date;publicclassTestMain{/***@paramargs*/publicstaticvoidmain(String[]args){//TODOAuto-generatedmethodstubUtilChild

深入剖析Java中的装箱和拆箱

自动装箱和拆箱问题是Java中一个老生常谈的问题了,今天我们就来一些看一下装箱和拆箱中的若干问题.本文先讲述装箱和拆箱最基本的东西,再来看一下面试笔试中经常遇到的与装箱.拆箱相关的问题. 一.什么是装箱?什么是拆箱? 在前面的文章中提到,Java为每种基本数据类型都提供了对应的包装器类型,至于为什么会为每种基本数据类型提供包装器类型在此不进行阐述,有兴趣的朋友可以查阅相关资料.在Java SE5之前,如果要生成一个数值为10的Integer对象,必须这样进行: Integer i = new I

深入剖析Java中的装箱和拆箱(转)

自动装箱和拆箱问题是Java中一个老生常谈的问题了,今天我们就来一些看一下装箱和拆箱中的若干问题.本文先讲述装箱和拆箱最基本的东西,再来看一下面试笔试中经常遇到的与装箱.拆箱相关的问题. 以下是本文的目录大纲: 一.什么是装箱?什么是拆箱? 二.装箱和拆箱是如何实现的 三.面试中相关的问题 一.什么是装箱?什么是拆箱? 在前面的文章中提到,Java为每种基本数据类型都提供了对应的包装器类型,至于为什么会为每种基本数据类型提供包装器类型在此不进行阐述,有兴趣的朋友可以查阅相关资料.在Java SE

[JAVA软件工程师-面试宝典-2013最新版]

[JAVA面试宝典-2013最新版] 一. Java基础部分......................................................................................................2 1.一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制?.....2 2.Java有没有goto?....................................................