了解栈内存堆内存

由于 java 有垃圾回收机制,所以往往不太会去关注栈堆的内存分配问题,直至OOM

一、了解栈堆概念

1、堆【存储对象创建实例】

  1. 程序开始运行时,JVM从OS获取一些内存,部分是堆内存。堆内存通常在存储地址的底层,向上排列。
  2. 堆是一个"运行时"数据区,类实例化的对象就是从堆上去分配空间的;
  3. 在堆上分配空间是通过"new"等指令建立的,堆是动态分配的内存大小,生存期也不必事先告诉编译器;
  4. 与C++不同的是,Java自动管理堆和栈,垃圾回收器可以自动回收不再使用的堆内存;
  5. 缺点是,由于要在运行时动态分配内存,所以内存的存取速度较慢。

2、栈【存放基本类型和引用类型】

  1. 先进后出的数据结构,通常用于保存方法中的参数,局部变量;
  2. 在java中,所有基本类型(short,int, long, byte, float, double,boolean, char)和引用类型的变量都在栈中存储;
  3. 栈中数据的生存空间一般在当前scopes内(由{…}括起来的区域;
  4. 栈的存取速度比堆要快,仅次于直接位于CPU中的寄存器;
  5. 栈中的数据可以共享,多个引用可以指向同一个地址;
  6. 缺点是,栈的数据大小与生存期必须是确定的,缺乏灵活性。

3、总结

  1. Java堆内存是操作系统分配给JVM的内存的一部分。
  2. 当我们创建对象时,它们存储在Java堆内存中。
  3. 你可以通过用JVM的命令行选项 -Xms, -Xmx, -Xmn来调整Java堆空间的大小。
  4. 栈中存放的基本类型数据:short,int, long, byte, float, double,boolean, char
  5. 只要采用 new 的形式创建对象,那么就存储在 java 堆内存中。

二、栈中的数据存储

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 == b true

2、包装类数据存储

如Integer, Double, String等将相应的基本数据类型包装起来的类。
这些类数据全部存在于堆中,Java用new()语句来显示地告诉编译器,在运行时才根据需要动态创建,因此比较灵活,但缺点是要占用更多的时间。

以String为例

String是一个特殊的包装类数据。即可以用String str = new String("abc");的形式来创建,也可以用String str = "abc";的形式来创建。
前者是规范的类的创建过程,即在Java中,一切都是对象,而对象是类的实例,全部通过new()的形式来创建。

那为什么在String str = "abc";中,并没有通过new()来创建实例,是不是违反了上述原则?其实没有。

关于String str = "abc"的内部工作。Java内部将此语句转化为以下几个步骤:

  • a、先定义一个名为str的对String类的对象引用变量:String str;
  • b、在栈中查找有没有存放值为"abc"的地址,如果没有,则开辟一个存放字面值为"abc"的地址,接着创建一个新的String类的对象O,并将O的字符串值指向这个地址,而且在栈中这个地址旁边记下这个引用的对象O。如果已经有了值为"abc"的地址,则查找对象O,并返回O的地址。
  • c、将str指向对象O的地址。
     值得注意的是,通常String类中字符串值都是直接存值的。但像String str = "abc";这种场合下,其字符串值却是保存了一个指向存在栈中数据的引用(即:String str = "abc";既有栈存储,又有堆存储)。

为了更好地说明这个问题,我们可以通过以下的几个代码进行验证。

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

只有在两个引用都指向了同一个对象时才返回真值。str1与str2是否都指向了同一个对象)

结果说明,JVM创建了两个引用str1和str2,但只创建了一个对象,而且两个引用都指向了这个对象。

3、总结

(1). 我们在使用诸如String str = "abc";的格式定义类时,总是想当然地认为,我们创建了String类的对象str。

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

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

(3). 由于String类的immutable性质(因为包装类的值不可修改),当String变量需要经常变换其值时,应该考虑使用StringBuffer类,以提高程序效率。

4、实例

String s = new String("abc") 创建了几个对象?

首先我们要明白两个概念,引用变量和对象,对象一般通过new在堆中创建,s只是一个引用变量。

答案2个。

5、知识点

我们可以用==判断一下两个引用变量是否指向了一个地址即一个对象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/414322.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

dataBinding和retrofit的使用

1、dataBinding使用方法 1、配置dataBinding 2、创建layout类型xml布局文件 3、即可引用 ActivityMainBinding mainBinding; mainBinding DataBindingUtil.setContentView(this, R.layout.activity_main); mainBinding.testte.setText("abcccc"); 2、retrofit的…

使多个线程循环输出0-99-0-99

直接上代码,后面我也有一个问题,关于对象的notifyAll或者notify或者single或者singleAll,唤醒线程是顺序唤醒吗,我这里都是顺序输出了 关于公平与非公平锁的问题?唤醒是公平的???又没…

66-Flutter移动电商实战-会员中心_编写ListTile的通用方法

1、界面分析 通过下图我们可以拆分成 4 部分,头部、订单标题区域、订单列表区域、ListTitle同用部分。 2、UI编写 2.1、头部 主要用到了圆形头像裁剪组件-ClipOval 顶部头像区域Widget _topHeader(){ return Container( width: ScreenUtil().setWidth(750), …

Android板实现双屏显示,DisplayManager和Display的使用

非常简单。 效果 1、创建分屏管理类 DisplayController public class DisplayController {public static Display getTargetDisplay() {DisplayManager displayManager (DisplayManager) App.getInstance().getSystemService(Context.DISPLAY_SERVICE);Display[] presentat…

毕业论文管理系统(类图,er图,时序图)

转载于:https://www.cnblogs.com/huahua985/p/8732595.html

67-Flutter中高德地图插件的使用

1、注册和建立高德API应用 高德网站:https://lbs.amap.com/ 控制台-应用管理-创建应用 在创建 Key 2、获得SHA1 进入Flutter项目中的android文件夹内,打开任意一个文件: 比如进入 build.gradle,右上角会有 Open for Editing an…

python列表

列表概念 • 有序的集合 • 通过偏移来索引,从而读取数据 • 支持嵌套 • 可变的类型 • 内置函数列表创建方式 定义列表: • 在python中定义列表需要使用方括号,列表中的项目都包含 在方括号中,项目之间使用逗号分隔。列表中的数…

onSaveInstanceState与onRestoreInstanceState何时调用、如何使用

简单使用实例 protected void onSaveInstanceState(Bundle outState) {// 被销毁前缓存一些数据outState.putString("name", "l_yqing");LgqLogPlus.d("进来了。。rw32r32。。。");super.onSaveInstanceState(outState); }protected void onRes…

Only fullscreen opaque activities can request orientation

安卓8异常 Only fullscreen opaque activities can request orientation 解决方法&#xff1a; android:theme"style/tDrawer" 添加如下属性 <item name"android:windowIsTranslucent">false</item> <item name"android:windowDis…

第八篇Django分页

Django分页 1.复杂版 data []for i in range(1, 302):tmp {"id": i, "name": "alex-{}".format(i)}data.append(tmp)print(data)def user_list(request):# user_list data[0:10]# user_list data[10:20]try:current_page int(request.GET.g…

20179214 《网络攻防实践》第五周学习

20179214 《网络攻防实践》第五周学习 web应用程序体系结构及其安全威胁 web应用程序体系结构 浏览器 标准的web客户端&#xff0c;Web服务器 通常被简单的描述为http守护程序&#xff0c;接受web客户端对资源的请求。Web应用程序 是处于服务器端的业务逻辑&#xff0c;最普遍的…

android studio 4.2.1 下载——安卓12开发

下载地址 &#xff1a;百度网盘 请输入提取码

MySQL -- SQL 语句

一. 数据库&#xff08;Database&#xff09;操作 创建数据库create database 数据库名 create database 数据库名 character set 字符集 查看数据库查看数据库服务器中的所有的数据库&#xff1a;show databases; 查看某个数据库的定义信息&#xff1a;show create database 数…

工作260:js判断一个数组是否包含一个指定的值

今天看了一下 有好几种方法 总结一下 1&#xff1a;array.indexOf 此方法判断数组中是否存在某个值&#xff0c;如果存在返回数组元素的下标&#xff0c;否则返回-1 let arr [something, anything, nothing, anything]; let index arr.indexOf(nothing); console.log(i…