一、内存介绍
java中的有六个不同的地方可以存储数据:
1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制。
2. 栈:存放基本类型的变量(基本数据类型常量放在常量池中)数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中) 。
3. 堆:存放所有new出来的对象。
4. 静态域:存放静态成员(static定义的)。
5. 常量池:存放字符串常量和基本类型常量(public static final)。
6. 非RAM存储:硬盘等永久存储空间 。
在这里主要讲一下栈、堆和常量池。对于栈和常量池中的对象可以共享(已存在就不创建),对于堆中的对象不可以共享。栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会消失。堆中的对象的由垃圾回收器负责回收,因此大小和生命周期不需要确定,具有很大的灵活性。
二、String的存储
对于字符串:其对象的引用都是存储在栈中的,如果是编译期已经创建好(比如String str = "hello")的就存储在常量池中,如果是运行期(new出来的)才能确定的就存储在堆中。对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份。
String s1 = "hello";//在常量池中
String s2 = new String("hello");//在堆中
创建s2时(new出来的),其实是先去常量池找是否存在hello对象,如果没有则在常量池中创建一个此字符串对象,然后堆中再创建一个常量池中此”hello”对象的拷贝对象。以上代码在创建s2时常量池中已存在hello,所以第二行代码是创建一个对象。
如果常量池中不存在,就是创建了两个对象。
三、基本数据类型的存储
对于基本数据类型(变量和常量),变量和引用是存储在栈中,常量存储在常量池中。
int i = 23 ;//栈中
public static final int j = 12 ;//常量池中
四、成员变量和局部变量的存储
局部变量的数据存在于栈内存中。栈内存中的局部变量随着方法的消失而消失。
成员变量存储在堆中的对象里面,由垃圾回收器负责回收。
下面举一个例子:
class Student{
public int age;
public Student(int a){
this.age = a;
}
}
public class Test{
public static void main(String args[]){
int day = 88;
Test test = new Test();
test.go(day);
Student s1= new Student(18);
}
public void go(int k){
k= 22;
}
解析:age为成员变量,a,day,k为局部变量。
①程序从main开始,int day = 88; 基本数据类型,局部变量,引用和值都在栈中。
②Test test = new Test();为引用类型,引用(test)在栈中,对象(new Test())在堆中。
③test.go(day);k为局部变量,引用和值都存在栈中,方法go执行完后,k就会在栈中消失。
④Student s1 = new Student(18);为引用数据类型,引用(s1)存储在栈,对象(new Student(18))存储在堆。 形参a是局部变量,⑤存储在栈当构造方法执行完,a就在栈中消失。而age为成员变量,它存储在堆(new Student(18))对象中。
⑥main执行完,day变量,test和s1引用将在栈中消失,而new Test();new Student();(对象)将等待垃圾回收器回收。