全部评论
没有亲身读过JVM源码,不过看过一些关于JVM的书,谈谈理解吧。从两个过程来看吧,编译和JVM运行时加载编译的时候,如果字符串就是常量,比如s1的时候就直接在字符串常量池放ABC,并让s1指向它,编译s2那行,发现它也是常量,就去池里找,发现没有DEF,就同样建立起来,s3也同理。到了s4,编译器发现是可以被优化的,因为没有其它对象的引用,即两个常量相加成了ABCDEF,这个串常量池里有了,所以就直接让s4也指向这个常量。到了s5.s6.s7,虽然在我们看来还是常量相加,但是编译器看来,这里涉及到的是对象引用,所以它会替换成引用符号,不做字符串常量池的查询和建立操作。JVM运行时加载的时候,常量池是最先分配完成的,也就是这时候s1.s2.s3.s4都有具体的常量池地址指向了,但是s5.s6.s7还需要解析里面的引用,这个过程中会分配新的内存地址让s5他们去指向,所以他们是完全不同的对象了。注: ==比较的应该不是引用所在的地址,而是引用的对象所在的地址,s3和s4是两个不同引用,但是都指向了同一个字符串常量池里的值。当然这里还有一个点,就是new String("ABCDEF"),你会发现还是跟s3相等,因为本质都是他们在编译器看来,没有涉及到任何引用,都是常量!都可以直接放在字符串常量池里!
s3在创建对象引用的时候,会去常量池查找是否存在字符串”ABCDEF”,然后它发现并不存在,所以它会将s3这个对象在堆中的引用地址存储一个到常量池中(jdk 7以及之后的版本);所以现在常量池中存储的地址就是堆中s3的地址,然后你创建s4,s4是两个衣服串常量想加,同样回去常量池中寻找地址,发现已经存在了,就把那个地址返回给s4。所以s3和s4就相等了,然后下面的3个操作因为都是新生成了对象,也就是在比较两个不同的对象,他们的内存地址是不会相同的
=右边有变量会在jvm中new一个新的,没有就复用
s5,s6,s7都是新的地址
常量池在方法区?变量在栈中?所以false?java大半年没用了🤣
不用==,用equals试试?
常量在编译时放入字符串常量池,表达式里有变量就只能runtime的时候new一个新的对象
加一个intern()方法就可以ture了
非java程序员,但还是知道java ==是判断内存地址是否相等,false说明内存地址不等,就牵扯出jvm内存管理模型了变量常量的存放区堆栈之类的,这些是要背一下的吧。
jdk1.8
2
1
相关推荐

点赞 评论 收藏
分享
点赞 评论 收藏
分享