您的位置:首页 > 编程语言 > Java开发

java中的堆栈

2016-05-24 20:02 211 查看

数据存放在哪里?

栈中存放的数据:基本类型数据对象引用的句柄(指向对象的地址)

堆中存放的数据:创建的对象

静态方法区存放的数据:字面量

例如:

String str = new String( "hello" );


上面的语句中变量str放在栈上,用new创建出来的字符串对象放在堆上,而"hello"这个字面量放在静态区。

数据类型的分类

基本类型

基本类型是比对象更小的单位,不是new出来的,有byte 、chart 、short 、int 、long 、float 、double 、boolean八种基本数据类型。变量直接包含了具体的值,存储在栈中。

引用类型

引用类型是指new出来的对象被放置在堆中,变量实际是指向一个对象的句柄。

堆栈的区别

1、栈是立即被访问的,而堆要跳几重寻址才能访问到,所以理论上栈的访问效率要比堆高,所以能用 int 就不要 new integer()

2、每个线程都有自己独立的栈,当方法执行完毕,栈里面的内存空间就会自动被回收,而堆在整个JVM中只有一个(所以堆中的数据可被多个线程共享),堆里面的内存空间由GC来负责回收。

3、静态方法也是全局只有一个实例,被所有线程共享。

引用类型变量赋值详解

demo1:

MyObject obj1;  // Step1
obj1 = new MyObject( ); //Step2
obj1.setName( "wxh" ); //Step3
MyObject obj2 = obj1; //Step4
obj2 = new MyObject( "wxh2" ); //Step5


Step1 -- Step2 :obj1由null变成存储指向MyObject对象的地址,存储在栈中,MyObject存储在堆中

Step2 -- Step3 :MyObject的name属性变成"wxh"

Step3 -- Step4 :obj2也指向了MyObject对象,值跟obj1相同

Step4 -- Step5 : 堆中创建了另外一个MyObject对象,obj2指向了该对象,obj1没变

demo2:基本数据类型的参数传递

public class Test {

public static void main(String[] args) {
Test test = new Test( );
int number = 100;
test.changeInt( number );
System.out.println( " 执行changeInt方法后:" + number );
}

public void changeInt(int value) {
value = 50;
System.out.println( "在方法内部:" + value );
}

}


运行结果:

在方法内部:50
执行changeInt方法后:100

其栈图如下:





demo3:引用数据类型的参数传递

public class Test2 {

public static void main(String[] args) {
Test2 test = new Test2( );
MyDate d = new MyDate( 1997, 7, 1 );
System.out.println( "执行方法前:" + d );
test.changeValue( d );
System.out.println( "执行方法后:" + d );
}

public void changeValue(MyDate date) {
date.setYear( 1999 );
date.setMonth( 12 );
date.setDay( 20 );
System.out.println( "在方法内部:" + date );
}

}


运行结果:

执行方法前:1997-7-1

在方法内部:1999-12-20

执行方法后:1999-12-20

说明对象内属性的值被修改了

堆栈图说明如下:

首先,执行MyDate d = new MyDate(1997,7,1) 时:



之后调用changeValue方法,传date变量进来,date变量接收的是d引用的地址:



修改堆内存中的数据为1999-12-20 时:



changeValue方法执行完出栈,此时d还是指向原来堆里面的内存,只是这个内存里面的值被修改了:



demo4:

public class Test2 {

public static void main(String[] args) {
Test2 test = new Test2( );
MyDate d = new MyDate( 1997, 7, 1 );
System.out.println( "执行方法前:" + d );
test.changeValue( d );
System.out.println( "执行方法后:" + d );
}

public void changeValue(MyDate date) {
date = new MyDate( 1999, 12, 20 );
System.out.println( "在方法内部:" + date );
}

}


运行结果:

执行方法前:1997-7-1

在方法内部:1999-12-20

执行方法后:1999-7-1

堆栈图说明如下:

执行MyDate d = new MyDate(1997,7,1) 时:



执行changeRef方法时:



changeRef方法执行:date = new Date(1992,12,20) :



changeRef方法执行后出栈,此时d仍然指向“1997-7-1”,而堆中的“1999-12-20”此时就没有了任何变量去引用,此时他就得等待GC来回收了:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: