zoukankan      html  css  js  c++  java
  • java中的堆栈

    数据存放在哪里?

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

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

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

    例如:

    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来回收了:

  • 相关阅读:
    组合数据类型练习
    Python基础综合练习
    编译原理
    词法分析
    大数据概述
    C语言文法分析 <源函数> → <外部声明> | <源程序> <外部声明> <外部声明> → <函数定义> | <定义> <函数定义> → <类型标识符> <声明部分语句> <标识符类型> → <无类型> | <字符> | <整型> | <浮点型> <声明> <指针直接声明> | <直接
    熟悉常用的Linux操作
    附加进程调试
    关于SQL语句中的nolock
    用SVN完成分支的合并
  • 原文地址:https://www.cnblogs.com/dahao1020/p/5524659.html
Copyright © 2011-2022 走看看