java中的堆栈

数据存放在哪里?栈中存放的数据:基本类型数据、对象引用的句柄(指向对象的地址)堆中存放的数据:创建的对象静态方法区存放的数据:字面量例如:上面的语句中变量str放在栈上,用new创建出来的字

数据存放在哪里?

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

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

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

例如:

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:

此代码由Java架构师必看网-架构君整理
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

其栈图如下:

java中的堆栈

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

此代码由Java架构师必看网-架构君整理
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) 时:

java中的堆栈

 

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

java中的堆栈

 

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

java中的堆栈

 

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

java中的堆栈

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) 时:

 

java中的堆栈

执行changeRef方法时:

java中的堆栈

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

java中的堆栈

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

java中的堆栈

 

本文来源大豪。,由架构君转载发布,观点不代表Java架构师必看的立场,转载请标明来源出处:https://javajgs.com/archives/42316
0

发表评论