以java‘==’理解内存分配

引言

public static void main(String[] args) {
	String str1 = new String("hello");
	String str2 = "hello";
	String str3 = new String("hello");
	String str4 = "hello";
	System.out.println(str1 == str2);
	System.out.println(str2 == str3);
	System.out.println(str3 == str4);
	String str5;// (str5 = str?)可以用==输出true?
}

先来一段java代码,如果上面变量都是int之类基本类型,也许结果显然全部相等。但是:

  • 如果现在是字符串呢?
  • 再换为随意创建的对象呢?
  • 再把==换为equals()呢?

分析

也许上面代码直接copy到Eclipse下瞬间便知答案,但是为什么?

首先定义了两组变量(str1,str2与str3,str4),方式一模一样,然后用==计算互相之间差异。
那么我们就要知道==在java中比较的是地址。好吧,貌似知道了也不能直接解题。似乎还必须了解它们存放地址在哪,这样才知道是否地址相等。那便一个一个分析变量存储内存(java内存介绍便不啰嗦了,可以看这儿)。

String str1 = new String("hello");

这段代码执行时,用了new关键字,于是在堆中创建了String对象,保存的值便是"hello"(任何对象创建都是类似)。然后在堆栈(栈)中保存一个引用类型(str1)[4个字节,保存地址]。而str1存放的是"hello"这个对象在堆中的地址(可以想象C中指针指向一个实际值,但是java中不存在指针这一说法)。于是每new一个对象,必然在堆中新分配了空间。对于String类型这是绝对的,而且只会在堆中保存对象。但是一个类存在的静态变量,会放在静态变量区,方法体等其他仍在堆中。

String str2 = "hello";

而执行这段代码时,str2仍然是栈中引用类型,但是java会先在常量池中寻找有没有"hello"这个字符串,如果有,那么str2就初始化为找到的"hello"的引用(不会在任何地方创建新对象)。如果没找到,会在常量池中创建,不同于new,堆中不创建对象。至此,在常量池中和堆中各有一个"hello"。继续:

String str3 = new String("hello");
String str4 = "hello";

接下来继续创建"hello"。str3时,又是new,想都不用想,前面str1分析中说了每次new都在堆中新创建对象。ok,现在堆中两个对象了,接着str4呢?继续在常量池创建?当然不,直接等号初始化是在常量池创建,但是前提是没有这个,而str2已经存在于常量池中,那么str4也就引用此处"hello"好了。至此所有创建的对象包括引用状态如下图:
内存状态
现在回到代码输出,比较地址?显然只有str2和str4引用同一个"hello" 地址,再其他任意两个地址都不相等。好吧,开始程序输出三个false.

然后根据自己想法创建一个str5,想等于str1?可以这样String str5 = str1,str3同理。如果想等于str2,或者str4呢,也可以这样?当然,而且还可以这样:

String str5 = "hello";//为什么?

思考

如果输出用equals()而不用==呢?

运行程序,或者直接得出:所有的str都相等。那么么么。。。为什么O(∩_∩)O~?

看来又要去了解equals()的比较方式

所有文章未特殊说明均属原创,有误之处欢迎提出,转载随意,您喜欢就好,但请注明,谢谢!
原文地址:https://www.cnblogs.com/nonefly/p/4603291.html