1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. 2. 栈(stack):存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中。) 3. 堆(heap):存放所有new出来的对象。 4. 静态域:存放静态成员(static定义的) 5. 常量池:存放字符串常量和基本类型常量(public static final)。 6. 非RAM存储:硬盘等永久存储空间
1.栈和常量池中的对象可以共享,堆中的对象不可以共享 2.栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会消失。堆中的对象的由垃圾回收器负责回收,因此大小和生命周期不需要确定,具有很大的灵活性。 3.对于字符串:其对象的引用都是存储在栈中的,如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才能确定的就存储在堆中。对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份。 String s1 = “Hello”; String s2 = “Hello”; String s3 = “Hello”; String ss1 = new String(“Hello”); String ss2 = new String(“Hello”); String ss3 = new String(“Hello”); s1,s2,s3,ss1,ss2,ss3叫做对象的引用,是放在栈中的
例子: Person p = new Person(); p就是你刚刚new 出来的那个对象的引用, p指向你刚刚new 出来的这个对象
“Hello”(直接用双引号定义的)字符串放在常量池里 new String(“Hello”)运行期(new出来的)才能确定的就存储在堆中 new出来的Hello时,回去常量池中查找是否有Hello对象,如果没有,则在常量池中创建一个此字符串对象,然后在堆中再创建一个常量池中的Hello的拷贝对象。 String s = new String(“hello”)若常量池中有此字符串对象,则产生一个hello对象吗,若常量池中没有,就是两个。
对于基础类型的变量和常量: 变量和引用存储在栈中 int i= 9; 常量存储在常量池中 public static final int INT = 9;
对于成员变量和局部变量:成员变量就是方法外部,类的内部定义的变量;局部变量就是方法或语句块内部定义的变量。局部变量必须初始化。 形式参数是局部变量,局部变量的数据存在于栈内存中。栈内存中的局部变量随着方法的消失而消失。 成员变量存储在堆中的对象里面,由垃圾回收器负责回收。 例子: class BirthDate { private int day; private int month; private int year; public BirthDate(int d, int m, int y) { day = d; month = m; year = y; } 省略get,set方法……… } public class Test{ public static void main(String args[]){ int date = 9; Test test = new Test(); test.change(date); BirthDate d1= new BirthDate(7,7,1997); } public void change1(int i){ i = 1234; } 步骤: 1.main方法执行,int date = 9 date是局部变量,基础类型,引用和值都在栈中。 2.Test test = new Test(); test为对象引用,存在栈中,对象(new Test())存在堆中。 3. test.change(date); i为局部变量,引用和值存在栈中。当方法change执行完成后,i就会从栈中消失。 4. BirthDate d1= new BirthDate(7,7,1970); d1为对象的引用,存在栈中,对象 new BirthDate()存在堆中,其中d,m,y为局部变量存储在栈中,且它们的类型为基础类型,因此它们的数据也存储在栈中,day,month,year为成员变量,它们存储在堆中(new BirthDate()里面)。当BirthDate构造方法执行完之后,d,m,y将从栈中消失。 5.main方法执行完之后,date变量,test,d1引用将从栈中消失,new Test(),new BirthDate()将等待垃圾回收. 包装类数据,如Integer, String, Double等将相应的基本数据类型包装起来的类。这些类数据全部存在于堆中,Java用new()语句来显示地告诉编译器,在运行时才根据需要动态创建,因此比较灵活,但缺点是要占用更多的时间。
==比较的是对象的地址,也就是是否是同一个对象; equal比较的是对象的值。