Java中的栈内存和堆内存

为什么我们常说基本类型传递的是具体的值,而对象传递的是对象的内存地址呢。要搞清楚这个问题就要搞清楚栈内存与堆内存。

java的内存分为栈内存和堆内存,两者的作用是不同的,我们可以简单的理解如下:

当我们创建一个java基本类型的变量时,只会用到栈内存而不会用到堆内存,栈内存中所存储的内容就是基本类型的值。

int a = 3;
  int b = 3;

执行第一行 int a = 3;时,JVM先会创建一个变量为a的引用,然后在栈内存中查找是否已经存在3这个值,没有找到,就会在栈内存中开辟一片区域存储3,然后将a指向存储3的位置。接着执行第二行int b=3;时也是先在栈内存中查找是否已经存在3这个值,是可以找到的,这时就将变量b的引用也指向存储3的位置。

当我们用new来创建一个非基本类型的对象时,就不仅要用到栈内存还要用到堆内存。

例如,Student s=new Student();

也会先在栈内存中开辟一块内存,用s指向这块内存,但这时栈内存存储的不是new Student(),而只是一个内存地址,这个内存地址就是在堆内存中存储new Student()的那块内存的首地址。

有了上面的概念,就可以解决一些简单的问题了。

第一个,我们都知道比较字符串的内容要用到equals(),而不是==,原因是什么呢

String s1=new String(“abc”);

String s2=new String(“abc”);

s1==s2 的结果是false,原因很简单,因为第一行和第二行都用到了new来产生新的对象,这两个对象在堆内存中的首地址肯定是不同的,那么s1所指向的栈内存中的内容与s2所指向的栈内存中的内容肯定是不同的,而==

比较的是栈内存,这时肯定是不相等的。

而equals方法我们可以理解为比较的是堆内存中的内容,由于两个堆内存中的内容都是abc,则必然是相等的。

第二个,把上面的稍微换一下

String s1=“abc”;

String s2=“abc”;

这时s1==s2,因为没有new,也就没分配堆内存,都是用的是栈内存,在执行第二行时,栈内存中已经存在了abc,则s2直接指向这个地址就可以了,所以会有s1==s2。

第三个,执行 String s1=“hello”;s1=s1+“world”的结果是怎样的呢

执行第一句时,会在栈内存中分配一块内存存储hello,执行第二句时,会分配一块新的内存存储hello world,而这时的s1指向的不再是hello的那块内存而是hello world的那块内存了。存储hello 的那块内存将会被垃圾回收器所回收。

第四个,我们常说复制基本类型时传递的是具体的值,而复制对象时传递的是对象的内存地址,这时候如果将栈内存和堆内存理解了,就可以明白是为什么了。

补充:

String a="abc"; 
String b="abc"; 
String c=new String("abc"); 
String d=c.intern();

因为引用变量c指向堆内存的地址;但是intern(); 却在栈中开辟了一块内存;其实c.intern(); 执行时,在栈内存中发现存在对象“abc”,所以直接将指针指向“abc”,这样 a == d, b==d 结果为true;

时间: 2024-10-07 06:07:11

Java中的栈内存和堆内存的相关文章

JVM存储位置分配——java中局部变量、实例变量和静态变量在方法区、栈内存、堆内存中的分配

Java中的变量根据不同的标准可以分为两类,以其引用的数据类型的不同来划分可分为“原始数据类型变量和引用数据类型变量”,以其作用范围的不同来区分可分为“局部变量,实例变量和静态变量”. 根据“Java中的变量与数据类型”中的介绍,“变量是在内存中分配的保留区域的名称.换句话说,它是一个内存位置的名称”,也就是说我们通过这个变量名字就可以找到一个指向这个变量所引用的数据的内存指针,根据变量的类型我们可以知道这个指针之后的几个字节里存储了这个变量所引用的数据. 所以,了解变量在方法区.栈内存.堆内存

栈内存和堆内存的区别

总结: 1 栈:为编译器自动分配和释放,如函数参数.局部变量.临时变量等等 2 堆:为成员分配和释放,由程序员自己申请.自己释放.否则发生内存泄露.典型为使用new申请的堆内容. 除了这两部分,还有一部分是: 3 静态存储区:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.它主要存放静态数据.全局数据和常量. 转自: 栈内存和堆内存的区别(一个笔试题的一部分)http://blog.csdn.net/richerg85/article/details/19175133 笔试

Java中对象、对象引用、堆、栈、值传递以及引用传递的详细解释

Java中对象.对象引用.堆.栈.值传递以及引用传递的详细解释 1.对象和对象引用的区别: (1).对象: 万物皆对象.对象是类的实例.在Java中new是用来在堆上创建对象用的.一个对象可以被多个引用所指向. (2).对象引用: 类似于C++中的地址.通过对象引用可以找到对象.一个引用可以指向多个对象.操纵的标识符实际上是指向对象的引用. 就像:对象存放在屋子里,对象的引用就相当于屋子的钥匙. 2.值传递和引用传递的区别: (1).值传递:传递的是值的拷贝.也就是说传递后就不互相关了. (2)

浅谈Java中的栈和堆

人们常说堆栈堆栈,堆和栈是内存中两处不一样的地方,什么样的数据存在栈,又是什么样的数据存在堆中? 这里浅谈Java中的栈和堆 首先,将结论写在前面,后面再用例子加以验证. Java的栈中存储以下类型数据,栈对应的英文单词是Stack 基本类型 引用类型变量 方法 Java的堆中存储以下类型数据,堆对应的英文单词是Heap 实例对象 在函数中定义的一些基本类型的变量(8种)和对象的引用变量都是在函数的栈Stack内存中分配.当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当

Java内存分配(直接内存、堆内存、Unsafel类、内存映射文件)

1.Java直接内存与堆内存-MarchOn 2.Java内存映射文件-MarchOn 3.Java Unsafe的使用-MarchOn 简单总结: 1.内存映射文件 读文件时候一般要两次复制:从磁盘复制到内核空间再复制到用户空间,内存映射文件避免了第二次复制,且内存分配在内核空间,应用程序访问的就是操作系统的内核内存空间,因此极大提高了读取效率.写文件同理. 2.堆内存分配与直接内存分配: Java申请空间时通常是从JVM堆内存分配的,即 ByteBuffer.allocate(int cap

JavaScript变量——栈内存or堆内存

原文  http://blog.csdn.net/xdd19910505/article/details/41900693 堆和栈这两个字我们已经接触多很多次,那么具体是什么存在栈中什么存在堆中呢?就拿 JavaScript 中的变量来说: 首先 JavaScript 中的变量分为基本类型和引用类型. 基本类型就是保存在栈内存中的简单数据段,而引用类型指的是那些保存在堆内存中的对象. 1 .基本类型 基本类型有 Undefined.Null.Boolean.Number 和String.这些类型

JavaScript 数据结构与算法之美 - 栈内存与堆内存 、浅拷贝与深拷贝

前言 想写好前端,先练好内功. 栈内存与堆内存 .浅拷贝与深拷贝,可以说是前端程序员的内功,要知其然,知其所以然. 笔者写的 JavaScript 数据结构与算法之美 系列用的语言是 JavaScript ,旨在入门数据结构与算法和方便以后复习. 栈 定义 后进者先出,先进者后出,简称 后进先出(LIFO),这就是典型的栈结构. 新添加的或待删除的元素都保存在栈的末尾,称作栈顶,另一端就叫栈底. 在栈里,新元素都靠近栈顶,旧元素都接近栈底. 从栈的操作特性来看,是一种 操作受限的线性表,只允许在

js的栈内存和堆内存

栈内存和堆内存在了解一门语言底层数据结构上,挺重要的,做了个总结 JS中的栈内存堆内存 JS的内存空间分为栈(stack).堆(heap).池(一般也会归类为栈中). 其中栈存放变量,堆存放复杂对象,池存放常量,所以也叫常量池. 栈数据结构 栈是一种特殊的列表,栈内的元素只能通过列表的一端访问,这一端称为栈顶.栈被称为是一种后入先出(LIFO,last-in-first-out)的数据结构.由于栈具有后入先出的特点,所以任何不在栈顶的元素都无法访问.为了得到栈底的元素,必须先拿掉上面的元素. 堆

【内存】堆内存和栈内存

栈内存 编译器自己自动创建和释放 (私有的,如函数参数,局部变量,临时变量) 堆内存 程序员自己创建和释放的 (公有的) 栈内存比堆内存访问速度快 栈内存比堆内存容量小 栈内存的生命周期短而堆内存在整个程序运行中都存在(非手动清除) ? 原文地址:https://www.cnblogs.com/china-flint/p/9909362.html