在这里我们只说一下jvm中的几个经常提到的存储区域。
堆:存放所有new出来的对象和数组(数组是一种特殊的对象);栈:局部变量和引用变量,new出来的对象本身并不存在栈中,而是存放在堆中或者常量池中(字符串常量对象存放在常量池中);常量池:存放基本类型常量和字符串常量,静态中存放静态成员(static定义的)。
栈中的数据大小和生命周期是可以确定的,当引用不在指向对象或者是局部变量出了作用域后,这个引用就会自动消失,该引用堆中的对象由垃圾回收器负责回收,但回收时间不确定,所以Java比较占内存的原因。
而对于字符串来说,其对象的引用都是存储在栈中的,如果是编译期已经创建好(即指用双引号定义的也就是不适用new关键字)的就存储在常量池中,如果是运行期(new出来的对象)则存储在堆中。对于equals相等的字符串,在常量池中是只有一份的,在堆中则有多份。
我们就在说一下常量池的相关知识:
String str= "abc";或者是String str=new String("abc");
String str2="abc";
String str3= new String ("abc");
String str4= new String ("abc");
创建str时,首先查找常量池中是否有该对象,若没有该对象,就会在常量池中创建,然后又在堆中创建该对象。当创建str2时,会发现常量池中已存在该对象,然后就会将该对象在常量池中的地址赋给str2,所以str=str2
而str3是通过new关键字生成的对象,首先也会在常量池中查找,发现已存在,就会存放在堆中,返回堆中该对象 的地址,而且我们知道,每new一次就会新生成一个对象。str4也是这样,所以str3不等于str4,当然了str2也不会等于str3。
引用变量的来源:通过new,在堆中产生了一个数组或者对象的同时,还可以在栈中定义一个变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或者对象,引用变量就相当于是为数组或者对象起的一个名称。引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放,如果在new时,没有指定引用变量,也就是匿名对象,在使用一次后就死亡了。
稍微有点Java基础的应该一看就明白了。我也就不在多上代码了。