Java把内存分成两种,一种叫做栈内存,一种叫做堆内存。

在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另作他用。

堆内存用于存放由new创建的对象和数组。在堆中分配的内存,由java虚拟机自动垃圾回收器来管理。在堆中产生了一个数组或者对象后,还可以在栈中定义一个特殊的变量,这个变量的取值等于数组或者对象在堆内存中的首地址,在栈中的这个特殊的变量就变成了数组或者对象的引用变量,以后就可以在程序中使用栈内存中的引用变量来访问堆中的数组或者对象,引用变量相当于为数组或者对象起的一个别名,或者代号。

引用变量是普通变量,定义时在栈中分配内存,引用变量在程序运行到作用域外释放。而数组&对象本身在堆中分配,即使程序运行到使用new产生数组和对象的语句所在地代码块之外,数组和对象本身占用的堆内存也不会被释放,数组和对象在没有引用变量指向它的时候,才变成垃圾,不能再被使用,但是仍然占着内存,在随后的一个不确定的时间被垃圾回收器释放掉。这个也是java比较占内存的主要原因,实际上,栈中的变量指向堆内存中的变量,这就是 Java 中的指针!

示例1如下:

Person per = new Person();

//这其实是包含了两个步骤,声明和实例化

Person per = null;  //声明一个名为Person类的对象per

per = new Person();  // 实例化这个per对象

声明 指的是创建类的对象的过程;

实例化 指的是用关键词new来开辟内存空间。

它们在内存中的划分是这样的:

那什么是栈内存(heap)和栈内存(heap)呢?

栈内存:

在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。栈内存主要存放的是基本类型类型的数据 如( int, short, long, byte, float, double, boolean, char) 和对象句柄。注意:并没有String基本类型、在栈内存的数据的大小及生存周期是必须确定的、其优点是寄存速度快、栈数据可以共享、缺点是数据固定、不够灵活。

栈的共享:

 1 String str1 = "myString";
 2
 3 String str2 = "myString";
 4
 5 System.out.println(str1 ==str2 );
 6
 7 //注意:这里使用的是str1 ==str2,而不是str1.equals(str2)的方式。
 8
 9 //因为根据JDK的说明,==号只有在两个引用都指向了同一个对象时才返回真值
10
11 //而str1.equals(str2),只是比较两个字符串是否相等

结果为True,这就说明了str1和str2其实指向的是同一个值。

上述代码的原理是,首先在栈中创建一个变量为str1的引用,然后查找栈中是否有myString这个值,如果没找到,就将myString存放进来,然后将str1指向myString。接着处理String str2 = "myString";;在创建完str2 的引用变量后,因为在栈中已经有myString这个值,便将str2 直接指向myString。这样,就出现了str1与str2 同时指向myString。

特别注意的是,这种字面值的引用与类对象的引用不同。假定两个类对象的引用同时指向一个对象,如果一个对象引用变量修改了这个对象的内部状态,那么另一个对象引用变量也即刻反映出这个变化。相反,通过字面值的引用来修改其值,不会导致另一个指向此字面值的引用的值也跟着改变的情况。如上例,我们定义完str1与str2 的值后,再令str1=yourString;那么,str2不会等于yourString,还是等于myString。在编译器内部,遇到str1=yourString;时,它就会重新搜索栈中是否有yourString的字面值,如果没有,重新开辟地址存放yourString的值;如果已经有了,则直接将str1指向这个地址。因此str1值的改变不会影响到str2的值。

堆内存:

堆内存用来存放所有new 创建的对象和 数组的数据

 1 String str1 = new String ("myString");
 2
 3 String str2 = "myString";
 4
 5 System.out.println(str1 ==str2 ); //False
 6
 7 String str1 = new String ("myString");
 8
 9 String str2 = new String ("myString");
10
11 System.out.println(a==b); //False

创建了两个引用,创建了两个对象。两个引用分别指向不同的两个对象。以上两段代码说明,只要是用new()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即使与栈中的数据相同,也不会与栈中的数据共享。

为了深入理解,添加了实例2:

 1 public class Demo1 {
 2
 3     public static void main(String[] args) {
 4
 5         String str1 = "hello";
 6         String str2 = "hello";
 7         String str3 = new String("hello");
 8         String str4 = new String("hello");
 9         System.out.println("str1==str2?"+(str1==str2));  // true
10         System.out.println("str2==str3?"+(str2==str3));  //false
11         System.out.println("str3==str4?"+(str3==str4));  // false
12         System.out.println("str3.equals(str2)?"+(str3.equals(str4))); //true
13         //是String类重写了Object的equals方法,比较的是两个字符串对象 的内容 是否一致。
14         // "=="用于比较 引用数据类型数据的时候比较的是两个对象 的内存地址,equals方法默认情况下比较也是两个对象 的内存地址。
15
16         test(null);
17     }
18
19 }

实行原理如下:

转载于:https://www.cnblogs.com/joyco773/p/6752037.html

Java中堆内存和栈内存的区别相关推荐

  1. Java中的堆内存、栈内存和方法区总结

    Java中内存分成两种,一种叫做栈内存,一种叫做堆内存.还有一个方法区,也叫做静态区. 1.栈内存中放哪些东西?  ①基本类型的变量,例如int a=3中的a:  ②对象的引用变量,例如Thread ...

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

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

  3. java 堆内存和栈内存的区别_java中栈内存和堆内存有什么区别

    栈内存和堆内存的区别: 1.栈内存用来存放基本类型的变量和引用变量,堆内存用来存储java中的对象,无论是成员变量,局部变量,还是类变量,他们指向的对象都存储在堆内存中. (视频教程推荐:java视频 ...

  4. python变量存储 堆与栈内存内存_浅析JS中的堆内存与栈内存

    最近跟着组里的大佬面试碰到这么一个问题, Q:说说var.let.const的区别 A:balabalabalabla... Q:const定义的值能改么? A:你逗我?不能吧 不知道各位看官怎么想? ...

  5. Java的堆内存和栈内存

    一.Java的堆内存和栈内存 Java把内存划分成两种:一种是堆内存,一种是栈内存. 堆:主要用于存储实例化的对象,数组.由JVM动态分配内存空间.一个JVM只有一个堆内存,线程是可以共享数据的. 栈 ...

  6. Java 堆内存和栈内存

    在Java中,内存:栈内存.堆内存. 1 栈内存 栈内存主要是用来执行程序用的,比如:基本类型的变量和对象的引用变量 栈溢出(StackOverflowError) 递归溢出 2 堆内存 堆内存作用是 ...

  7. js中的堆内存和栈内存

    转自:https://www.cnblogs.com/heioray/p/9487093.html 浅析JS中的堆内存与栈内存 最近跟着组里的大佬面试碰到这么一个问题, Q:说说var.let.con ...

  8. java堆内存和栈内存的区别

    一段时间之前,我写了两篇文章文章分别是Java的垃圾回收和Java的值传递,从那之后我收到了很多要求解释Java堆内存和栈内存的邮件,并且要求解释他们的异同点. 在Java中你会看到很多堆和栈内存的引 ...

  9. 栈和堆存储在计算机RAM中,堆内存和栈内存及C++内存分配

    1.现代操作系统内存管理主流的操作系统(Windows,Linux)都采用虚拟内存管理的方式,具体说就是:页式管理.段式管理.段页式管理. 操作系统分配资源的单位是进程,所以,内存管理的过程也是以进程 ...

  10. C++中的堆内存、栈内存和静态内存

    C++中的堆内存.栈内存和静态内存 C++中的空间主要分为三类,堆内存.栈内存和静态内存,其中静态内存用来存储全局对象(定义在任何函数之外的对象).局部static对象.类static数据成员,栈内存 ...

最新文章

  1. 美国波特兰市禁用人脸识别,被违规监控可获赔1000美元
  2. linux与安卓系统目录,android系统架构及源码目录结构
  3. java 并发编程实例_Java并发编程案例解读
  4. html中正方形列表标签属性,如何在HTML中创建带有方形项目符号的无序列表?
  5. 知乎: 如何评价阿里开源的企业级 Node.js 框架 egg? #18
  6. python用空格隔开每一个字符_python实现将一串字符每两个一组,中间用空格隔开...
  7. 北京的小伙伴,本周五阿里聚安全约你来玩
  8. 检测工控设备SNMP漏洞工具:SNMP Fuzzer
  9. ResourceExhaustedError 解决方案
  10. PhotoShop基础——如何抠图
  11. matlab飞机飞行模型,使用 MATLAB/Simulink 设计无人机飞行控制系统(二、动力学模型建立)...
  12. C++超详细五子棋游戏(AI实现人机对弈+双人对弈+EasyX图形化界面+详细介绍)
  13. 零售门店营业额预测分析(时间序列建模)
  14. 最新版本供需指标介绍,自动识别有价值的K线,超级好用
  15. Calcite 原理解析
  16. 前端权限管理方案之精确到按钮级别
  17. 软件测试面试复习题(一)
  18. 《CSS 世界》读书笔记-流与宽高
  19. 最近在玩微博,觉得微博学习到了一点东西,分享下
  20. 用javascript编写的地址二级联动

热门文章

  1. python的shutil模块是内置的_python内置模块~shutil
  2. 未找到“SocialiteProviders \ Manager \ ServiceProvider”类
  3. PHP 空数组转Json字符串的问题
  4. 提升技能必备网站(不定时更新)
  5. 使用jps查看JAVA进程号
  6. AndroidStudio是最难用的IDE,没有之一
  7. LINUX编译opencore-amr
  8. debian编译openjdk8
  9. 解决办法:用户名不在 sudoers文件中 此事将被报告
  10. deb官方源、国内源