zoukankan      html  css  js  c++  java
  • 细说 栈 为什么又被称为 栈堆 ?【得从数组变量讲起】

    1.前言

      上一篇随笔【 https://www.cnblogs.com/c2g5201314/p/13111591.html 】总结了 栈 与 堆 ,栈是栈 ,堆是堆 ,不是一个东西,

    但 又 明确地指出了栈 ,又称为栈堆 ,这是为什么呢?

      这一篇随笔将详细说明 栈堆 的由来。 

      这就得从数组的定义讲起了。

    2.数组

    看一段关于数组的代码

        @Test
        public void t2() {
            int[] num = null;
            num = new int[2];
            num[0] = 1;
            num[1] = 2;
            System.out.println(Arrays.toString(num));
        }

    运行后打印结果

     我们知道,栈是用于存放函数的参数值 和局部变量的值 ,

    那么在这段代码中 , 局部变量 num 将会存在栈里面 ,

    new 表示开辟存储空间 ,那么到底在哪里开辟存储空间呢?

    其实是在里面 ,

    new int[2] 表示在里面 开辟一个长度为2 的数组 空间 ,此时数组每个元素 的私有空间 是空的。

    通过赋值  num =  使得 元素 num 的 数据指针指向 堆 里长度为2 的数组 空间 的地址 ,

    也就是说 ,栈是存储 变量的名称 ,而堆是存储变量的 对象内容,

    当赋值的时候 ,将会改变堆中数组的值。

    //

    再看一段代码

    @Test
    public void t2() {
    int[] num = null;
    num = new int[2];
    num[0] = 1;
    num[1] = 2;
    System.out.println(Arrays.toString(num));
    int[] data = null;
    data = num;
    System.out.println(Arrays.toString(data));
    data[0]=10;
    System.out.println(Arrays.toString(data));
    System.out.println(Arrays.toString(num));
    }

     打印结果

     多了 data = num;  进行数组赋值 ,

    那么底层到底是怎么实现的?难道又新建了一个栈名为data的变量,在队列又开辟了个空间然后拷贝数据么?

    实际上并非如此。

    //

    int[] data = null;表示新定义了个 名叫 data的局部变量 ,存在栈里 新分配的一个空间中,此时data 没有对应的堆内容,

     data = num;  时 将会把 num指向的堆内容地址传给data ,data将会指向该堆地址,也就是说,两个栈空间会指向同一个 堆空间 ,

    将会共同支配同一个 堆 的内容。

    data[0]=10; 则是对该堆空间数组的第一个元素赋值 ,将原值为1 改成了 10 。

    打印结果 【10 ,2】没有问题。

    然后再次打印 num ,结果仍然是 【10 ,2】,

    可证明 两个栈空间确实 是 指向了 同一个 堆空间 ,即数据共享了。

     

    问题来了,如果我希望在赋值给 data 的同时,保留 num 数值不变,该怎么办?

    那其实也是很简单 ,只需要给data开辟一个单独的 空间 后 再赋值即可,

    看代

     @Test
        public void t2() {
            int[] num = null;
            num = new int[2];
            num[0] = 1;
            num[1] = 2;
            System.out.println(Arrays.toString(num));
            int[] data ;
            data = num.clone();
            System.out.println(Arrays.toString(data));
            data[0]=10;
            System.out.println(Arrays.toString(data));
            System.out.println(Arrays.toString(num));
        }

     打印结果

     给 data 赋值的时候是用来 clone()方法 ,意为克隆 ,

    底层实现是

     

     效果是一样的 ,

    其实就是给data 开辟新的堆空间后给每个元素赋值的过程。

    【不仅仅是数组,包含对象的任意类型的变量也是 栈 与 堆配合实现的,如果赋的值是常量,那么该常量则存在常量池中,不是存在堆中的

     3.回归正题

      上一节 ,详细 解释了 数组变量的底层 原理,指出了 栈是存储 变量的名称 ,而堆是存储变量的对象内容 这一结论,

    因此 如果仅仅定义变量,却不赋值,仅仅会在栈开辟空间存储变量名称 ,如果给变量赋值,将会把值存在堆中 ,栈会指向这个堆的地址 ,

    这就是 栈堆 这一称呼的由来。

  • 相关阅读:
    1. 单个文件下载
    16. js方法传多个参数的实例
    15. combobox、combotree获取显示值和value值方式
    38. 查看oracle表空间存放的位置(查看所有的数据库文件的存放位置)
    Vuejs 高仿饿了么外卖APP 百度云视频教程下载
    mysql 5.7 百度云网盘下载
    mysql 5.1 下载地址 百度云网盘下载
    Zookeeper学习笔记-概念介绍
    JavaScript工程师都应懂的33个概念
    IIS部署asp.net MVC 出现错误 403.14-Forbidden解决办法
  • 原文地址:https://www.cnblogs.com/c2g5201314/p/13111873.html
Copyright © 2011-2022 走看看