zoukankan      html  css  js  c++  java
  • 数据存储在哪里,堆?栈?

    thinking in java 读书笔记(感悟);
    页码:P9 (想看书上怎么讲的。自行翻看 P22 页)
    
    写于:2018年3月29日21:09:48
    
    作者:淮左白衣
    

    目录


    先说明下一些名字的概念,以前我曾以为寄存器是内存;(大笑。。。。)

    寄存器

    寄存器,是最快的存储区域了,因为寄存器在CPU的内部!近水楼台先得月嘛,执行效率杠杠的;千万不能因为它是速度快,以为这货就是内存,笔者以前就是因为它快,在学java的时候,老师讲过内存读取是很快的,快过硬盘的;就以为金寄存器是内存。。。


    栈,位于RAM中。RAM怎么说呢,是随机访问存储器的简写;懂了吗?反正我当初不懂什么是随机访问存储器,又跑去百度随机访问存储器;得出一个结论:RAM可以不严谨的称为内存;之所以不严谨,是因为RAM也不是内存,只是内存中一个至关重要的存储单元;姑且,称之为内存吧;

    栈的访问速度非常快,仅次于寄存器 ;

    栈中的数据是共享的!这句话,请记住!


    堆,同样位于内存中;


    常量池

    存放那些实例不可改变的量;比如字符串,这里不是所有的字符串都在这存放在这里;对了,多说一句,基本类型的包装类,也是不可改变的 ;


    硬盘

    持久化存储


    上面的废话,终于讲完了,进入正题!我们平时写的代码,那些变量、对象这些数据存放在哪里?

    场景(int a = 4 ; 背后的故事)

    int a = 3 ;
    int b = 3 ;
    a = 4 ;
    
    String str1 = "淮左白衣" ;
    String str2 = new String("淮左白衣");

    请问这些代码的背后发生了什么?或者它们在内存中怎么存储的?

    ——————————— 我一句一句代码讲 ———————————-

    int a = 3 ;

    在栈中开辟一片空间,存储 3 这个字面值;然后继续在栈中开辟空间,存储引用a ,并把引用a 指向 3 那片地址 ;

    int b = 3 ;

    先在栈中查找是否有 3 这个字面值存在,如果有,就直接使用(栈中的数据是共享的);如果没有,则开辟空间,存储 3 这个字面值 ;

    在我们这里是有的,因此只会在栈中开辟存储引用 b 的空间;然后把引用b指向 3 那片地址 ;

    a = 4 ;

    同样,先在栈中查找是否有 4 这个字面值存在,如果有,就直接使用;如果没有,则开辟空间,存储 4 这个字面值 ;

    在我们这里,是没用的,因此,先在栈中开辟空间,存储字面值 4 ,然后把 引用 a ,重新指向存储字面值 4 的那片地址 ;这里注意引用 b 的指向的 3 是不受影响的 ;

    下面的两句代码,一句代码,就能讲一个故事了,因此,另起段落写 ;


    String str1 = “淮左白衣” 背后的故事

    第一步:首先在字符串常量池中查找是否有 “淮左白衣” 这个字符串;如果没有的话,则在常量池中,创建一个 “淮左白衣” 的字符串,然后,划重点,这一步网上许多资料都没有说出来,在 中,创建一个字符串对象,但是这个字符串对象的字面值,是一个引用,而不是字符串,这个引用,就指向常量池中的那个 “淮左白衣” 这个字符串对象,常量池中的“淮左白衣” 对象,同样也持有堆上的那个字符串对象的引用 ;在栈中创建一个引用 str ,引用指向常量池中的对象持有的堆上的对象的地址

    第二步:如果有的话,则直接在栈中创建引用 str ,然后让引用,指向常量池中那个“淮左白衣”对象所持有的引用 ;


    String str1 = new String(“淮左白衣” ) ; 这背后的故事又是什么呢

    第一步:先去常量池中寻找是否有“淮左白衣”这个字符串对象,如果有的话,则在堆中,拷贝一个这个对象 ;然后把堆中的这个对象的地址,返回给栈中的 str ;

    第二步:如果,常量池中没有“淮左白衣”这个对象,则先在常量池中创建一个“淮左白衣”字符串对象;然后,去堆中,拷贝一个这个对象;后把堆中的这个对象的地址,返回给栈中的 str ;


    故事讲到这里,已然完结,谢幕吧!(掌声、鲜花。。。)


    ちょっと待って

    等一下,还有一些东西忘记说了 ;

    String str1 = "abc" ;
    String str2 = "ab" + "c" ;
    String str3 = new String("ab") + "c" ;

    上面的3个引用,使用“ == ” 符号来运算;
    str1 == str2 ; true
    str1 == str3 ; false
    str2 == str3 ; false

    原因是:

    String str2 = "ab" + "c" ;

    对于这样的代码,编译期间,编译器会进行优化,因为“ab”、“c” 都是确定的值,编译器会自动将它们优化为:

    String str1 = "abc" ;

    因此,str1 == str2 是true ;而对于 new String(“ab”) 这样的东西,编译期间,无从得知,它们具体是什么,也就无法优化了 ,只能在堆中创建对象了 ;


    备注

    常量池有许多,什么Integer、Long、Strng啊等等,都有自己的常量池;文中所说的常量池,均指字符串常量池 ;*

  • 相关阅读:
    Promise笔记
    srping-cloud-stream集成rocketmq
    mysql锁
    profiling分析
    mysql慢查询
    sql语句中in与exists的使用区别
    数据库死锁的解决办法
    死锁的形成以及处理
    百万数据修改索引,百万数据修改主键
    创建视图索引
  • 原文地址:https://www.cnblogs.com/young-youth/p/11665744.html
Copyright © 2011-2022 走看看