java栈和堆

Java - 数据结构,栈 java虚拟机栈也是栈,就是JVM中的一块内存,也是符合栈的规则 – 先进后出规则方法区:存放类定义信息、字节码、常量等数据,在Sun HotSpot JVM中,这块也称为Perm Gen。堆:创建的对象信息将放入堆中,堆内部如何实现各虚拟机各不相同,对于Sun HotSpot JVM来说又分为Young Gen和Tenured Gen,更详细描述参见《[Java性能剖析]Sun JVM内存管理和垃圾回收 》 阅读详情

                java栈与堆的思考

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

        2. 栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外,栈数据可以共享,详见第3点。堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。

        3. Java中的数据类型有两种。
  一种是基本类型(primitive types), 共有8种,即int, short, long, byte, float, double, boolean, char(注意,并没有string的基本类型)。这种类型的定义是通过诸如int a = 3; long b = 255L;的形式来定义的,称为自动变量。值得注意的是,自动变量存的是字面值,不是类的实例,即不是类的引用,这里并没有类的存在。如int a = 3; 这里的a是一个指向int类型的引用,指向3这个字面值。这些字面值的数据,由于大小可知,生存期可知(这些字面值固定定义在某个程序块里面,程序块退出后,字段值就消失了),出于追求速度的原因,就存在于栈中。
  另外,栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义

  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与 b的值后,再令a=4;那么,b不会等于4,还是等于3。在编译器内部,遇到a=4;时,它就会重新搜索栈中是否有4的字面值,如果没有,重新开辟地址存放4的值;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。
  另一种是包装类数据,如Integer, String, Double等将相应的基本数据类型包装起来的类。这些类数据全部存在于堆中,Java用new()语句来显示地告诉编译器,在运行时才根据需要动态创建,因此比较灵活,但缺点是要占用更多的时间。

        4. String是一个特殊的包装类数据。即可以用String str = new String("abc");的形式来创建,也可以用String str = "abc";的形式来创建(作为对比,在JDK 5.0之前,你从未见过Integer i = 3;的表达式,因为类与字面值是不能通用的,除了String。而在JDK 5.0中,这种表达式是可以的!因为编译器在后台进行Integer i = new Integer(3)的转换)。前者是规范的类的创建过程,即在Java中,一切都是对象,而对象是类的实例,全部通过new()的形式来创建。Java 中的有些类,如DateFormat类,可以通过该类的getInstance()方法来返回一个新创建的类,似乎违反了此原则。其实不然。该类运用了单例模式来返回类的实例,只不过这个实例是在该类内部通过new()来创建的,而getInstance()向外部隐藏了此细节。那为什么在String str = "abc";中,并没有通过new()来创建实例,是不是违反了上述原则?其实没有。

        5. 关于String str = "abc"的内部工作。Java内部将此语句转化为以下几个步骤:
  (1)先定义一个名为str的对String类的对象引用变量:String str;
   (2)在栈中查找有没有存放值为"abc"的地址,如果没有,则开辟一个存放字面值为"abc"的地址,接着创建一个新的String类的对象o,并将o 的字符串值指向这个地址,而且在栈中这个地址旁边记下这个引用的对象o。如果已经有了值为"abc"的地址,则查找对象o,并返回o的地址。
  (3)将str指向对象o的地址。
  值得注意的是,一般String类中字符串值都是直接存值的。但像String str = "abc";这种场合下,其字符串值却是保存了一个指向存在栈中数据的引用!
  
  为了更好地说明这个问题,我们可以通过以下的几个代码进行验证。

  String str1 = "abc";
  String str2 = "abc";
  System.out.println(str1==str2);  //true
  
  注意,我们这里并不用str1.equals(str2);的方式,因为这将比较两个字符串的值是否相等。==号,根据JDK的说明,只有在两个引用都指向了同一个对象时才返回真值。而我们在这里要看的是,str1与str2是否都指向了同一个对象。
  结果说明,JVM创建了两个引用str1和str2,但只创建了一个对象,而且两个引用都指向了这个对象。

  我们再来更进一步,将以上代码改成:

  String str1 = "abc";
  String str2 = "abc";
  str1 = "bcd";
  System.out.println(str1 + "," + str2);  //bcd, abc
  System.out.println(str1==str2);  //false

  这就是说,赋值的变化导致了类对象引用的变化,str1指向了另外一个新对象!而str2仍旧指向原来的对象。上例中,当我们将str1的值改为"bcd"时,JVM发现在栈中没有存放该值的地址,便开辟了这个地址,并创建了一个新的对象,其字符串的值指向这个地址。
   事实上,String类被设计成为不可改变(immutable)的类。如果你要改变其值,可以,但JVM在运行时根据新值悄悄创建了一个新对象,然后将这个对象的地址返回给原来类的引用。这个创建过程虽说是完全自动进行的,但它毕竟占用了更多的时间。在对时间要求比较敏感的环境中,会带有一定的不良影响。

  再修改原来代码:

  String str1 = "abc";
  String str2 = "abc";
  
  str1 = "bcd";
  
  String str3 = str1;
  System.out.println(str3);  //bcd

  String str4 = "bcd";
  System.out.println(str1 == str4);  //true
    
  str3 这个对象的引用直接指向str1所指向的对象(注意,str3并没有创建新对象)。当str1改完其值后,再创建一个String的引用str4,并指向因str1修改值而创建的新的对象。可以发现,这回str4也没有创建新的对象,从而再次实现栈中数据的共享。

  我们再接着看以下的代码。

  String str1 = new String("abc");
  String str2 = "abc";
  System.out.println(str1==str2);  //false

  创建了两个引用。创建了两个对象。两个引用分别指向不同的两个对象。

  String str1 = "abc";
  String str2 = new String("abc");
  System.out.println(str1==str2);  //false

  创建了两个引用。创建了两个对象。两个引用分别指向不同的两个对象。

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

        6. 数据类型包装类的值不可修改。不仅仅是String类的值不可修改,所有的数据类型包装类都不能更改其内部的值。

        7. 结论与建议:

   (1)我们在使用诸如String str = "abc";的格式定义类时,总是想当然地认为,我们创建了String类的对象str。担心陷阱!对象可能并没有被创建!唯一可以肯定的是,指向 String类的引用被创建了。至于这个引用到底是否指向了一个新的对象,必须根据上下文来考虑,除非你通过new()方法来显要地创建一个新的对象。因此,更为准确的说法是,我们创建了一个指向String类的对象的引用变量str,这个对象引用变量指向了某个值为"abc"的String类。清醒地认识到这一点对排除程序中难以发现的bug是很有帮助的。

  (2)使用String str = "abc";的方式,可以在一定程度上提高程序的运行速度,因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于String str = new String("abc");的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象,从而加重了程序的负担。这个思想应该是享元模式的思想,但JDK的内部在这里实现是否应用了这个模式,不得而知。

  (3)当比较包装类里面的数值是否相等时,用equals()方法;当测试两个包装类的引用是否指向同一个对象时,用==。

  (4)由于String类的immutable性质,当String变量需要经常变换其值时,应该考虑使用StringBuffer类,以提高程序效率。


原文来自:http://topic.youkuaiyun.com/u/20081123/12/f70f1632-24be-4caa-bc20-29cf8267afab.html

基于PCIe的NVMe协议在FPGA中实现方法 NVMe协议是工作在PCIE的最上层协议层的,故需要先搞清楚PCIE。本文基于Xilinx的UltraScale+,开发工具为Vivado2021.2。NVMe的学习仍以spec为主,其它资料辅助理解,有冲突时以spec为准,必要时可对比最新版本spec。(此文重点介绍学习方法及资料,有时间再加细节)。 主要参考的文章是《老男孩读PCIe》,同时参考《古猫先生》,重点学习TLP报文部分,数据链路层和物理层的内容可以先不看。再买一本书《PCI Express 体系结构导读-王齐》用来查阅做笔记。 阅读详情

相关推荐

centos7下100T存储扩容(LVM)至150T

查看新增磁盘情况lsblk,fdisk -l [root@localhost ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sr0 11:0 1 4.2G 0 rom vda 252:0 0 80G 0 disk ├─vda1 252:1 0 1G 0 part /boot └─vda2 252:2

tiyager的博客 1024

深入理解Java中的栈(超详细)新手必看

栈(Stack)是一种常见的数据结构,具有后进先出(LIFO,Last In First Out)的特性,即最后入栈的元素最先出栈。栈通常用于存储临时性的数据,如方法调用过程中的局部变量、操作数栈等。在计算机科学中,栈的应用非常广泛,包括编程语言中的函数调用、内存分配以及表达式求值等领域。在Java编程语言中,栈也被广泛应用于方法调用和内存管理的过程中。双端栈(Double Ended Stack),也被称为双端队列(Deque),是一种支持在两端进行插入和删除操作的数据结构。

2201_75437633的博客 2万+

华为C语言笔试题(附答案)

华为C语言笔试题(附答案)     1、局部变量能否和全局变量重名?   答:能,局部会屏蔽全局。要用全局变量,需要使用 ":: "   局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。对于有些编译器而言,在同一个函数内可以定义多个同名的局部变量,比如在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内。  

峰云四起 3030

Java数据结构-栈

栈

Vampire的博客 5641

Palabos User Guide中文解读 | 第一章 | 介绍

译者的话:本人在学习palabos时,发现国内中文资料甚少,恰好网上可以直接搜到palabos user guide这种英文资料,加之时间充裕,便打算开始翻译,能不能完成全本翻译再说,而且文中我也会标记我不确定的地方,以传达意思为主,翻译不当的地方还请各位读者帮忙指正。 Palabos User Guide Release 1.0 r1 Copyright © 2019 University of...

Yulan Fang's notes. 6977

Dify社区版多工作空间功能解锁:源码修改与多租户架构解析

多租户架构是现代SaaS平台实现数据隔离与资源管理的核心技术,其核心原理是通过租户模型将用户、应用和数据在逻辑上隔离。在AI应用开发平台中,这种架构能有效支持多团队、多项目并行开发,确保不同业务线的数据安全与独立迭代。Dify作为开源AI应用构建平台,其底层已设计完善的多租户模型,但社区版默认限制了单用户单工作空间。本文通过精准修改两处关键代码——账户初始化逻辑与系统功能开关,释放了平台固有的多工作空间管理能力。该方案无需改动数据库结构,直接利用现有RBAC权限体系,实现了类似企业版的**多租户隔离**体验

weixin_27059669的博客 1051

Java数据结构01——栈

java java数据结构 栈

qq_64037280的博客 4385

基于CODESYS与EtherCAT的步进电机单轴控制实践

本文详细介绍了基于CODESYS平台与EtherCAT总线技术实现步进电机单轴控制的完整实践流程。从硬件选型、软件工程创建、EtherCAT主从站配置,到运动控制功能块编程与在线调试,手把手指导读者完成从零到一的搭建,并提供了常见问题的排坑指南,帮助自动化开发者快速掌握这一高效、灵活且成本可控的工业运动控制解决方案。

hh234的博客 491

java中的栈

本文阐述了对栈数据结构的理解,展示了继承关系,针对Stack被弃置的问题展开了探讨,具体解释了被弃置的原因,如何替代,使用队列实现栈的算法以及在面试中如何看待Stack。

Archiea的博客 1万+

C语言新手必练:10个实战小项目带你快速上手(附完整代码)

本文为C语言初学者精选10个实战项目,从基础的温度转换器到高级的迷宫求解算法,涵盖输入输出、条件判断、循环控制、数组操作等核心知识点。每个项目配有完整代码和详细解析,帮助新手通过实践掌握编程思维,特别适合刚学完语法但缺乏实战经验的学习者。

weixin_29208077的博客 736

用 ABAP ADK 写一个可控的自建表归档程序:从选择屏幕到 ARCHIVE_SAVE_OBJECT 的完整链路

文章摘要: 本文介绍了SAP系统中数据归档的核心概念与实践方法。归档旨在将不常访问但需保留的数据从在线数据库移出,以减轻系统负载,同时满足合规要求。文章重点阐述了: 归档与备份、重组的本质区别 SAP归档框架的核心组件:归档对象(AOBJ)、归档管理界面(SARA)和ADK开发工具包 通过YAPTMAIN表示例,展示了完整的归档流程: 使用选择屏幕控制归档范围 管理归档会话 写入归档记录 生成统计报表 强调了归档程序设计中需要考虑的运维、审计和性能因素 该方案可有效解决自建日志表"悄悄长胖&quo

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 227

java中栈和堆的区别

栈(stack)和堆(heap)都是java 用来在RAM中存放数据的地方,与C++不同,java是自动管理栈和堆,程序员不能直接的设置栈和堆。在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。 当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。 堆 ...

没有到不了的明天 4688

彻底解决JDK安装包点击后无反应

jdk双击无法安装,jdk双击没反应,jdk安装包双击后没反应。

renkai721的专栏 8937

Java堆和栈

堆(Heap)是Java程序中的动态内存区域,用于存储对象和数组。堆的大小在程序运行时动态变化,可以通过JVM的参数进行设置。堆中的对象需要通过new操作符来创建,创建后自动分配内存空间。

程序猿老白~的博客 6547

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Java中堆和栈的区别

堆和栈都是Java用来在RAM中存放数据的地方。 堆 (1)Java的堆是一个运行时数据区,类的对象从堆中分配空间。这些对象通过new等指令建立,通过垃圾回收器来销毁。 (2)堆的优势是可以动态地分配内存空间,需要多少内存空间不必事先告诉编译器,因为它是在运行时动态分配的。但缺点是,由于需要在运行时动态分配内存,所以存取速度较慢。 栈 (1)栈中主要存放一些基本数据类型的变量(byte,short,int,long,float,double,boolean,char)和对象的引用。 (2)栈的优势是,存取速

欢迎关注公众号:【码农突围】,公号后台回复9999,可以获取一份500页的LeetCode刷题笔记。 4203

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

java栈和堆的区别_Java中堆和栈的区别

堆和栈都是Java用来在RAM中存放数据的地方。堆(1)Java的堆是一个运行时数据区,类的对象从堆中分配空间。这些对象通过new等指令建立,通过垃圾回收器来销毁。(2)堆的优势是可以动态地分配内存空间,需要多少内存空间不必事先告诉编译器,因为它是在运行时动态分配的。但缺点是,由于需要在运行时动态分配内存,所以存取速度较慢。栈(1)栈中主要存放一些基本数据类型的变量(byte,short,int,...

weixin_33515785的博客 4654

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

JAVA中的堆和栈

在JAVA的内存空间中,存在重要的两个内容便是JAVA的堆和栈,两者都用来存放数据,但又有所区别。当你用各种工具使用java语言编写了一段程序,当这段程序被运行的时候,在java中的内存会有五块区域进行数据的存储,分别为程序计数器,本地方法区,方法区,堆,栈。1.堆就相当于当你new一个对象的时候,就会分配一个堆内存给你,当对象销毁时就会有垃圾回收机制来回收这个对象的堆空间。2.栈就好比一串珠子,你只能从一头加或者取,要取后面的就要把前面的取出来才可以。3.堆内存作用就是用来存放java中的对象和数组,当n

weixin_63834061的博客 4636

java中堆 栈的英文_Java中的栈和堆

人们常说堆栈堆栈,堆和栈是内存中两处不一样的地方,什么样的数据存在栈,又是什么样的数据存在堆中?这里浅谈Java中的栈和堆首先,将结论写在前面,后面再用例子加以验证。Java的栈中存储以下类型数据,栈对应的英文单词是Stack基本类型引用类型变量方法栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变...

weixin_33147807的博客 2553

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

JAVA在程序运行时,在内存中划分5片空间进行数据的存储。分别是:1:寄存器。2:本地方法区。3:方法区。4:栈。5:堆。基本,栈stack和堆heap这两个概念很重要,不了解清楚,后面就不用学了。以下是这几天栈和堆的学习记录和心得。得些记录下来。以后有学到新的,会慢慢补充。一、先说一下最基本的要点基本数据类型、局部变量都是存放在栈内存中的,用完就消失。new创建的实例化对象及数组,是存放在堆内存...

weixin_36457551的博客 601

java 中的堆和栈

包含最全MySQL、Redis、Java并发编程等等面试题和答案,用于参考~

2401_83641360的博客 936

java的堆和栈

数组都是有一个索引,数组这个实体在堆内存中产生之后每一个空间都会进行默认的初始化(这是堆内存的特点,未初始化的数据是不能用的,但在堆里是可以用的,因为初始化过了,但是在栈里没有),不同的类型初始化的值不一样。堆内存存储的是数组和对象(其实数组就是对象),凡是new建立的都是在堆中,堆中存放的都是实体(对象),实体用于封装数据,而且是封装多个(实体的多个属性),如果一个数据消失,这个实体也没有消失,还可以用,所以堆是不会随时释放的,但是栈不一样,栈里存放的都是单个变量,变量被释放了,那就没有了。...

m0_52261367的博客 3267

Java堆和栈的区别

Java堆和栈作为Java虚拟机内存管理的重要组成部分,在存储方式、内存特点、垃圾回收机制和使用场景等方面有着显著的区别。理解这些区别可以帮助我们更好地编写高效、稳定的Java程序。在实际开发中,需要根据程序的特性和需求选择合适的数据结构和算法,合理地利用堆和栈的优势来提高程序的性能和稳定性。同时,也需要关注堆和栈的使用情况,避免出现内存溢出或者资源过度消耗的问题。

编程思维 1423

【java】堆和栈的总结

栈中用来存放一些原始数据类型的局部变量数据和对象的引用(String,数组.对象等等)但不存放对象内容堆中存放使用new关键字创建的对象.字符串是一个特殊包装类,其引用是存放在栈里的,而对象内容必须根据创建方式不同定(常量池和堆).有的是编译期就已经创建好,存放在字符串常 量池中,而有的是运行时才被创建.使用new关键字,存放在堆中。

DreamSun的博客 459

Java 中的堆和栈

综上,堆和栈在 Java 内存管理中分工明确,堆负责对象的长期存储和共享访问,栈专注于方法执行过程的临时数据处理,它们协同保障 Java 程序的正常运行,理解二者区别对分析内存问题(如内存泄漏、溢出 )、优化程序性能至关重要。

weixin_43521001的博客 1099

Java堆、java栈

Java堆: Java堆内存空间在虚拟机启动时创建,是Java虚拟机锁管理的最大内存区域;垃圾收集器的主要区域;它被所有线程共享。堆内存的唯一目的是存放对象实例。 Java堆空间分为老年代和新生代。老年代用于存储经过多次GC(垃圾回收)后,任然存活的对象,或者是创建的大对象(新生代空间不足,会直接将大对象存放在老年代);新生代主要用于存储新创建的对象,新生代又分为Eden区、From Surv...

zhoushimiao1990的博客 980
上一篇: StringUtils常用方法
下一篇: Class.newInstance()学习
myjava_024
博客等级 码龄20年 59粉丝 45原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值