黑马程序员技术交流社区

标题: 关于String 的 问题 [打印本页]

作者: 牧风    时间: 2016-7-30 22:05
标题: 关于String 的 问题
String  s= "abdc";
String s2  = new String ("abdc");
为什么两个都是创建了对象?? 规定??求解释

作者: cat73    时间: 2016-7-30 22:14
本帖最后由 cat73 于 2016-7-31 01:05 编辑

实际上只有第二句创建了对象。
具体解答:http://bbs.itheima.com/forum.php ... 580&pid=2642261


作者: 牧风    时间: 2016-7-30 22:20
cat73 发表于 2016-7-30 22:14
实际上只有第二句创建了对象。

C:\Users\mf\Desktop
第一次发这个帖子 不知道怎么在贴吧发截图 你看能看到吗

QQ图片20160730221844.png (8.12 KB, 下载次数: 30)

QQ图片20160730221844.png

作者: cat73    时间: 2016-7-30 22:33
牧风 发表于 2016-7-30 22:20
第一次发这个帖子 不知道怎么在贴吧发截图 你看能看到吗

实际上这个答案是错误的 "abc" 并不是在执行这个语句的时候创建的。
作者: showJiang    时间: 2016-7-30 22:39
一个在常量池,一个在堆内存,
作者: 牧风    时间: 2016-7-30 23:08
cat73 发表于 2016-7-30 22:33
实际上这个答案是错误的 "abc" 并不是在执行这个语句的时候创建的。

能回答的详细一点吗
作者: shockzwel1    时间: 2016-7-30 23:22
两个对象  只是新建的位置不同而已
作者: 18072727834    时间: 2016-7-30 23:24
只有第二句创建了对象
作者: 牧风    时间: 2016-7-30 23:25
shockzwel1 发表于 2016-7-30 23:22
两个对象  只是新建的位置不同而已

就是说是规定 一个在堆 内存 一个在常量池是吧?
作者: shockzwel1    时间: 2016-7-30 23:26
Java中  有很多 规定  你要自己懂。
作者: 牧风    时间: 2016-7-30 23:27
shockzwel1 发表于 2016-7-30 23:26
Java中  有很多 规定  你要自己懂。

秒懂了= = = = = = = =算了 洗洗睡了
作者: 孤峰无悔    时间: 2016-7-30 23:30
s进栈 s2进堆内存
作者: shockzwel1    时间: 2016-7-30 23:31
同学  来一把狼人杀吧
作者: 孤峰无悔    时间: 2016-7-30 23:32
只要创建了对象就会在堆内存出现,明显s没进堆内存,所以不算创建对象

作者: cat73    时间: 2016-7-30 23:40
本帖最后由 cat73 于 2016-7-30 23:42 编辑
牧风 发表于 2016-7-30 23:08
能回答的详细一点吗

等你以后研究深入一些大概就明白了。。。
"abc" 是通过 ldc 获取的,ldc 的字符串是在解析阶段创建的。
相关文档:
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.3
作者: qetu001212    时间: 2016-7-31 00:01
这个设计到常量池和堆内存,第一个指向常量池,第二个指向堆内存
作者: qetu001212    时间: 2016-7-31 00:02
cat73 发表于 2016-7-30 22:14
实际上只有第二句创建了对象。

在常量池也应该是创建了对象的啊
作者: qetu001212    时间: 2016-7-31 00:04
cat73 发表于 2016-7-30 23:40
等你以后研究深入一些大概就明白了。。。
"abc" 是通过 ldc 获取的,ldc 的字符串是在解析阶段创建的。
相 ...

为何冯佳老师和你说的不一样?
作者: cat73    时间: 2016-7-31 00:16
qetu001212 发表于 2016-7-31 00:02
在常量池也应该是创建了对象的啊

常量池当然要创建对象呀,但是这个对象是在执行这个语句的时候创建的么?
作者: HeiMa2Wangkunpe    时间: 2016-7-31 00:31
s实在字符串常量池中创建  s2堆内存中创建对象
作者: HeiMa2Wangkunpe    时间: 2016-7-31 00:33
s实在字符串常量池中创建  s2堆内存中创建对象
作者: cat73    时间: 2016-7-31 01:02
本帖最后由 cat73 于 2016-7-31 09:25 编辑
qetu001212 发表于 2016-7-31 00:04
为何冯佳老师和你说的不一样?

如果你认为我说错了,请拿证据打我脸,但请不要说这是谁说过的。谢谢。
为了回答这个问题,我花了些时间去看 OpenJDK 的源代码:
http://hg.openjdk.java.net/jdk8/jdk8/hotspot/file/87ee5ee27509/src/share/vm/interpreter/bytecodeInterpreter.cpp#l2111
在上面这个地方可以看到 ldc 的实现
2134 行是 ldc String 的情况:
[C++] 纯文本查看 复制代码
          case JVM_CONSTANT_String:
            {
              oop result = constants->resolved_references()->obj_at(index);
              if (result == NULL) {
                CALL_VM(InterpreterRuntime::resolve_ldc(THREAD, (Bytecodes::Code) opcode), handle_exception);
                SET_STACK_OBJECT(THREAD->vm_result(), 0);
                THREAD->set_vm_result(NULL);
              } else {
                VERIFY_OOP(result);
                SET_STACK_OBJECT(result, 0);
              }
            break;
            }

可以看到,ldc 只是简单的从常量池里尝试获取对象,如果返回 null (没找到),则抛出异常,并不会在 ldc 这里 new String。

而 "abc" 就是通过 ldc 来获取的,也就是说,"abc" 不是 ldc 创建的,所以,这句代码执行的时候并不会创建"abc",所以,这句代码只创建了一个对象。

有兴趣的话也可以看看 ldc 的规范:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.ldc
作者: ylca    时间: 2016-7-31 09:04
一个是拿一个是创建
作者: Bingo8888    时间: 2016-7-31 09:48
一个在方法区的常量池中,一个NEW在堆内存中
作者: zhuqing    时间: 2016-7-31 09:54
第一个在常量池,第二个在堆内存,地址值不同
作者: qetu001212    时间: 2016-7-31 10:05
cat73 发表于 2016-7-31 01:02
如果你认为我说错了,请拿证据打我脸,但请不要说这是谁说过的。谢谢。
为了回答这个问题,我花了些时间去 ...

初学者,在学基础,看不懂源码,已送上3黑马币请求原谅~~~
作者: 牧风    时间: 2016-7-31 11:10
shockzwel1 发表于 2016-7-30 23:31
同学  来一把狼人杀吧

你也玩网杀?
作者: cat73    时间: 2016-8-1 23:52


作者: cat73    时间: 2016-8-2 01:12
本帖最后由 cat73 于 2016-8-2 01:15 编辑
qetu001212 发表于 2016-7-31 00:04
为何冯佳老师和你说的不一样?

https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5.5
  1. The run-time constant pool for a class or interface is constructed when the class or interface is created (§5.3) by the Java Virtual Machine.
复制代码

一个更精准的描述,常量是在类加载时创建的。
所以下面的代码只创建了一个对象
new String("abc");

这条规范在 Java 6 就已经有了:https://docs.oracle.com/javase/specs/jvms/se6/html/Overview.doc.html#22972


作者: zhangjiesss    时间: 2016-8-2 08:26
第一个常量池,第二个有两个对象,一个是在堆内存中创建String类对象,一个是在常量池中创建“abcd”对象




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2