Java中堆、栈和常量池的区别

栈 堆 常量池的概念

首先我们先了解一下概念,Java把内存分成两种,一种叫做栈内存,一种叫做堆内存。

栈内存

存放基本类型的变量数据和对象类型的引用(请注意存放的是引用),对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中)

堆内存

堆内存用来存放由new创建的对象和数组。在堆中分配的内存,由java虚拟机自动垃圾回收器来管理

常量池

存放字符串常量和基本类型常量(public static final)

堆栈的比较

一般来说,栈的速度比堆的速度要快,那为什么还要引入堆呢?这就要涉及到堆栈的优缺点了。

栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享(指的是线程共享,而给进程共享)。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。

堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要 在运行时动态分配内存,存取速度较慢。

##奇怪的问题

在学习java堆栈的知识时,也遇到一点有趣的小问题,我很奇怪,查了很多资料后发现有不同的说法。

对于String s=new String("abc");的创建

一种说法:对于通过new产生一个字符串(假设为”abc”)时,会先去常量池中查找是否已经有了”abc”对象,如果已经创建"abc",则不会继续创建。如果没有则在常量池中创建一个此字符串对象,然后堆中再创建一个常量池中此”abc”对象的拷贝对象。一个是编译时决定的,最后放在常量池中。一个是运行时放在堆里面的。

另一种说法:1、首先在堆中(不是常量池)创建一个指定的对象"abc",并让str引用指向该对象 2、在字符串常量池中查看,是否存在内容为"abc"字符串对象 3、若存在,则将new出来的字符串对象与字符串常量池中的对象联系起来 4、若不存在,则在字符串常量池中创建一个内容为"abc"的字符串对象,并将堆中的对象与之联系起来 intern 方法可以返回该字符串在常量池中的对象的引用

String str1 = "abc";

一种说法:

栈中开辟一块空间存放引用str1,

String池中开辟一块空间,存放String常量"abc",

引用str1指向常量池中String常量"abc",

str1所指代的地址即常量"abc"所在地址,输出为true

另一种说法:先在栈中创建一个对String类的对象引用变量str1 ,然后查找栈中有没有存放"abc",如果没有,则将"abc"存放进栈,并令str1 指向"abc",如果已经有"abc",则直接令str1 指向"abc"

对于上述两个问题的两种说法,本人均更倾向于第一种说法,因为第一种说法对程序有优化的作用,第二种说法是多此一举,并未带来任何好处。

讨论:int a=1;那么这个1是存在栈里还是存在常量池?

对于这个问题我也困惑了好久,首先可以肯定的a是int类型的引用,存储在栈里,那么这个1到底是存在哪里呢? 我们通常的理解是1作为一个常量肯定是存储在常量池中啊。在查阅了很多资料后发现,这个1是存储在栈中,并未存储在常量池中。 这里我们需要注意的是对于1我们看起来是常量,但j虚拟机却并不是将其看作是常量而是一个变量,只有声明为final类型的数据JVM才会将其看做是常量,而常量池是存放字符串常量和基本类型常量(public static final)的,所以这里的1是存储在栈里的。

实例分析

我们举一个最常见的例子,分析一下栈基本的处理过程:

int a = 3; int b = 3;

编译器会先处理int a = 3;,首先它会在栈中创建一个变量为a 的引用,然后查找栈中是否有3 这个值,如果没找到,就将3存放进来,然后将a 指向3 。接着处理int b = 3; ,在创建完 b 的引用变量后,因为在栈中已经有3 这个值,便将b 直接指向3 。 这样,就出现了 a 与 b 同时均指向 3 的情况。这时,如果再令 a = 4;,那么编译器会重新搜索栈中是否有 4 这个值,如果没有,就将4 存放进来,并令a 指向 4;如果已经有了,则直接将 a 指向这个地址。 因此a值的改变不会影响到 b 值。 要注意这种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的,因为这种情况 a 的修改并不会影响到 b,它是由编译器完成的,它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态,会影响到另一个对象引用变量。

总结以及需要注意的地方

对于字符串:其对象的引用都是存储在栈中的,如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才能确定的就存储在堆中。

对于基本类型应该不会用到常量池,因为基本类型的值就存在栈中,在Java中对基本类型变量的运算、判断以及赋值都是对值的操作,没有对地址操作,例如:int a = 1; int b = 2; a = b; 这是将b的值赋给a,而不是a引用b;

我们在使用诸如String str = "abc";的格式定义类时,总是想当然地认为,我们创建了String类的对象str。请注意,对象可能并没有被创建!唯一可以肯定的是,指向 String类的引用被创建了。至于这个引用到底是否指向了一个新的对象,必须根据上下文来考虑,除非你通过new()方法来显要地创建一个新的对象。因 此,更为准确的说法是,我们创建了一个指向String类的对象的引用变量str,这个对象引用变量指向了某个值为"abc"的String类。

java堆和栈 常量池_GitHub - han-guang-xue/difference-of-stack-heap-pool: Java中堆、栈和常量池的区别...相关推荐

  1. Java中堆、栈、常量池等概念解析

    Java中堆.栈.常量池等概念解析 程序运行时,我们最好对数据保存到什么地方做到心中有数.特别要注意的是内存的分配.有六个地方都可以保存数据: (1) 寄存器.这是最快的保存区域,因为它位于和其他所有 ...

  2. JAVA中堆和栈的区别

    堆:(对象) 引用类型的变量,其内存分配在堆上或者常量池(字符串常量.基本数据类型常量),需要通过new等方式来创建. 堆内存主要作用是存放运行时创建(new)的对象. (主要用于存放对象,存取速度慢 ...

  3. java内存堆和栈_java中堆,栈主要区别及内存存储

    java堆.栈.堆栈的区别 1.栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆. 2. 栈的优势是,存取速度 ...

  4. java中堆和栈的区别!!!!

    Java的堆是一个运行时数据区,类的(对象从中分配空间.这些对象通过new.newarray.anewarray和multianewarray等 指令建立,它们不需要程序代码来显式的释放.堆是由垃圾回 ...

  5. java什么是栈和堆_JAVA中的栈和堆

    JAVA在程序运行时,在内存中划分5片空间进行数据的存储.分别是:1:寄存器.2:本地方法区.3:方法区.4:栈.5:堆. 基本,栈stack和堆heap这两个概念很重要,不了解清楚,后面就不用学了. ...

  6. 简述JAVA中堆内存与栈内存的区别

    Java把内存划分成两种:一种是栈内存,一种是堆内存. 一.栈内存 存放基本类型的变量,对象的引用和方法调用,遵循先入后出的原则. 栈内存在函数中定义的"一些基本类型的变量和对象的引用变量& ...

  7. 常见Java面试题之解释内存中的栈、堆和静态区用法

    栈(stack).堆(heap)和静态区(static area)的用法区别 * 通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用内存中的栈空间: * 通过new关 ...

  8. Java - 解释内存中的栈(stack)、堆(heap)和静态区(static area)的用法

    分享一个大牛的人工智能教程.零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请点击http://www.captainbed.net 通常我们定义一个基本数据类型的变量,一个对象的引用, ...

  9. 让你彻底明白JAVA中堆与栈的区别

    原文地址:http://www.2cto.com/kf/201302/190704.html 简单的说: Java把内存划分成两种:一种是栈内存,一种是堆内存. 在函数中定义的一些基本类型的变量和对象 ...

最新文章

  1. python画图程序飞机_Python海龟画图工具绘制叮当猫程序
  2. mysql server uuids_slave have equal MySQL Server UUIDs原因及解决
  3. Fastboot和Recovery
  4. 可逆加密算法 php,php可逆加密的方法及原理
  5. lisp 线性标注自动避让_CAD局部放大图如何标注对应的尺寸,才能保持尺寸值不变...
  6. Swift和Objective-C混编注意事项
  7. NuGet.org服务管理变更,提升中国用户体验
  8. java char指针数组_简单总结C语言中各种类型的指针的概念
  9. npm上传自定义vue组件入门
  10. 企业实战|CentOS8安装Zabbix 4.4
  11. python函数装饰器详解_Python语言函数装饰器用法实例详解
  12. LiveNVR传统安防摄像机互联网直播-主要功能模块及相关技术特点与性能指标
  13. 免费在线逻辑图 + 示例
  14. highcharts pie ajax,Basic Pie
  15. 连续分配存储管理,覆盖交换和存储碎片
  16. 基于RV1126 Video分析-----驱动各模块总览
  17. 500G技术资源分享
  18. 《仗剑啸江湖》技术支持
  19. 成语学习微信小程序源码
  20. 杭州的红绿灯竟然是位“诗人”在管

热门文章

  1. SQL查询的安全方案
  2. [转]大数据环境搭建步骤详解(Hadoop,Hive,Zookeeper,Kafka,Flume,Hbase,Spark等安装与配置)
  3. 【数据库原理及应用】经典题库附答案(14章全)——第四章:关系系统及其优化
  4. ENVI支持下利用高分辨率影像城市绿地信息提取方案
  5. linux之通过strings命令查看so里面是否包含****字符串
  6. 最大尺寸分辨率_未来就在眼前——视涯科技推出最高分辨率硅基OLED显示屏幕...
  7. bootstrap bootstraptable 固定列_1个Excel公式按条件自定义格式显示固定电话号码
  8. 最诡异数学悖论:1+1=1
  9. 动力强劲的星型发动机,为何不用在汽车上呢?
  10. 仿真模拟,需要注意这几点!