Java把内存分为栈内存和堆内存。栈内存保存的只是数组的名称,即使用“数据类型 数组名”就可以开辟栈内存,但只开辟栈内存的数组是不能被直接使用的。因为堆内存是用来存放数组实体的,若想使用数组则需要用new关键字来开辟堆内存,然后把堆内存的控制权交给栈内存,一个堆内存可以被多个栈内存引用。
以下程序举例:
//开辟栈内存
int arrayInt[]=null;
//开辟堆内存
arrayInt=new int[5];
声明int arrayInt[]=null;
时,编译器中栈内存中分配一块内存空间给arrayInt
用来保存指向数组实体的地址空间。声明之后,执行arrayInt=new int[5];
,编译器在堆内存中开辟出了一个可以保存5个int型的内存空间,并将地址返回给arrayInt
变量(该变量在栈内存中)。
再用字符串来举个例子。Java中比较两个字符串一般用到以下两种方式:
第一,使用“==”来比较,用于判断基本数据类型的变量值是否相等,或者判断引用数据类型变量的引用地址是否相同。
第二,使用对象的equals()
方法,用于判断对象的引用地址所指向的存储空间内容是否相等。
通过以下代码分析:
public static void main(String[] args) {
String str1="Java";
String str2=new String("Java");
if(str1==str2){
System.out.println("str1==str2 :true");
}else{
System.out.println("str1==str2 :false");
}
if(str1.equals(str2)){
System.out.println("str1.equals(str2) :true");
}else{
System.out.println("str1.equals(str2) :false");
}
}
String类型的内容是保存中堆内存的,栈内存只保存指向堆内存的地址。使用直接赋值产生的String对象会用到Java的缓冲机制。在执行String str1="Java";
时,中缓冲池内并没有”Java”字符串,所以生成一个“Java”字符串,若此时再执行一句String str12="Java";
缓冲池中已经存在”Java”字符串了,所以不需要重新生成一个新的“Java”字符串而是直接使用该字符串,即它们在栈内存中地址指向堆内存中相同的地方。
使用new关键字调用构造方法生成字符串时,不会用到缓冲池机制。每调用一次就会在堆内存中开辟新的空间 ,str1和str2在栈内存中指向的地址不同,使用==比较当然两者是不同的,而它们执行的不同地址的堆内存中保存的内容是相同的,这时用equals()
方法比较,它们也就”相等“了。
简单来说,栈内存保存的是数组变量名称即数组在堆内存中的地址。堆内存保存数组实体。