在学习过程中,经常会遇到字符串的 == 和 equals 两种比较方式。
其中, == 比较的是的内存地址,而equals比较的是内容(好理解)
下面,结合Java虚拟机的简单内存图,讨论一下 == 方法有关的个人理解。
Java内存的简单分区(结合自己做的图分析)
1.栈:线程私有,通常存储的是对象的引用
2.堆:线程共享,通常存储对象
3.方法区:线程共享 ,通常存储常量、静态变量、已加载的类信息等
4.其他:不做讨论
5.由于String类的的存在,如果每次想获得一个字符串都要在堆内存开辟空间new一个新对象的话,会很大浪费内存。故规定在方法区加入字符串常量池这一概念,当以“String s = "abc"”形式获取“abc”对象时,分两步(1)判断常量池是否有“abc”对象,有的话,将引用指向该地址(2)如果没有,则在常量池新建对象,并将地址指向引用,如图方法区部分s1,s2,s3,s4。
6.由Java类每次new新对象都会在堆中开辟新空间,并把地址指向引用(这点不过多解释),如图中s5,s6
7.个人总结:String s = "a" 方式 与 new String("a") 所创建的对象没有任何关系,一个存在方法区,一个存在堆,故遇到这类题目,搞清引用指向即可。
8.输出分析(按图中输出先后顺序)
1>s1 s2都在常量区,地址相同
2>s1在常量区,s5在堆 ,地址不同
3>s4+"" 相当于new了新字符串对象,故在堆中,与常量池中的s1地址不同
4>虽然两者都在堆,但地址依然不同