Java变量在内存中的存储

以下探究成员变量局部变量在内存中的存储情况。

package com.my.pac04;

/**
* @author Summerday
* @date 2019/12/1 13:05
*/
public class ValStoreTest {
public static void main(String[] args) {
//分别创建两个Value类的实例,val0和val1
Value val0 = new Value();
Value val1 = new Value();
//修改val0的num值
val0.num = 5;
System.out.println("val0's num = " + val0.num);//val0'num =5
System.out.println("val1's num = " + val1.num);//val0'num =0 //直接使用类调用类变量
Value.staticNum = 10;
//使用实例对象调用类成员变量,不建议使用
//val0.staticNum = 10;
System.out.println("val0's staticNum =" + val0.staticNum);//10
System.out.println("val1's staticNum =" + val1.staticNum);//10
}
}
class Value {
public int num;//实例变量
public static int staticNum;//类变量
}

成员变量

上面提到成员变量分为实例变量和类变量。这两者在内存中的存储形式又是如何呢?

class Value {
public int num;//实例变量
public static int staticNum;//类变量
}

实例变量

Value val0 = new Value();
Value val1 = new Value();
//修改val0的num值
val0.num = 5;
System.out.println("val0's num = " + val0.num);//val0'num =5
System.out.println("val1's num = " + val1.num);//val0'num =0
  • 堆区开辟内存,存放实例变量,并默认初始化。
  • 栈区声明引用变量val0和val1,让他们分别存储两个堆区对象的地址,意思是让引用变量指向实际对象。
  • 两个对象分别独立,互不影响。

类变量

//直接使用类调用类变量
Value.staticNum = 10;
//使用实例对象调用类成员变量,不建议使用
//val0.staticNum = 10;
System.out.println("val0's staticNum =" + val0.staticNum);//10
System.out.println("val1's staticNum =" + val1.staticNum);//10
  • 方法区(不是栈区)存储static修饰的变量,即staticNum。
  • 两个引用变量val0和val1还是在栈区存储,且他们指向方法区的同一块内存区域。
  • 在同一个类中,实例对象共享类变量。意思是,如果Java程序运行在不同JVM进程中,就不会共享数据。如下:
package com.my.pac04;
/* ClassVal.java */
public class ClassVal {
public static int value = 6;
}
package com.my.pac04;
/* ClassValTest01.java */
public class ClassValTest01 {
public static void main(String[] args) {
ClassVal val01 = new ClassVal();
val01.value = 10;//修改static修饰的值为10
System.out.println(val01.value);
}
}
package com.my.pac04;
/* ClassValTest02.java*/
public class ClassValTest02 {
public static void main(String[] args) {
ClassVal val02 = new ClassVal();
System.out.println(val02.value);//不是10,而是6
}
}

关于JVM及类加载的机制,在之后的学习之中将会继续深入,在这里就不发表自己的肤浅之谈了,之后会进行补充哈。


局部变量

  • 定义局部变量时,只有对他进行初始化赋值之后,才会获得系统给予的内存。
  • 局部变量不属于类或实例,总是保存在栈内存中,所以随方法或代码块结束而结束,后进先出。
  • 基本数据类型存放具体数值,引用类型存放实际引用对象的地址值

注意:虽然大部分时间,可以之间用成员变量来代替局部变量解决问题,但是这种做法,有几个缺点:

  • 增大变量的生存时间,增加内存开销。
  • 扩大变量的作用域,不利于提高程序的内聚性。

局部变量的作用范围越小,它在内存中停留的时间就越短,程序性能就会越好。

总结

  • 假如定义的变量用于描述某个类或对象的固有信息,请用成员变量。
  • 假如定义的变量用于保存类或实例运行的状态信息,请用成员变量。
  • 假如定义的变量用于保存共享在多个方法间的消息,请用成员变量。

Java变量在内存中的存储的更多相关文章

  1. python中变量在内存中的存储与地址关系解析、浅度/深度copy、值传递、引用传递

    ---恢复内容开始--- 1.变量.地址 变量的实现方式有:引用语义.值语义 python语言中变量的实现方式就是引用语义,在变量里面保存的是值(对象)的引用(值所在处内存空间的地址).采用这种方式, ...

  2. 详解Python变量在内存中的存储

    这篇文章主要是对python中的数据进行认识,对于很多初学者来讲,其实数据的认识是最重要的,也是最容易出错的.本文结合数据与内存形态讲解python中的数据,内容包括: 引用与对象 可变数据类型与不可 ...

  3. PHP变量在内存中的存储方式

    原文:http://www.phppan.com/tag/refcount/ 每门计算机语言都需要一些容器来保存变量数据.在一些语言当中,变量都有特定的类型,如字符串,数组,对象等等.比如C和Pasc ...

  4. Java常量,变量,对象(字面量)在JVM内存中的存储位置

    Java常量,变量,对象(字面量)在JVM内存中的存储位置 2019-02-26 18:13:09 HD243608836 阅读数 540  收藏 更多 分类专栏: JAVA jvm   苦苦研究了快 ...

  5. String在内存中如何存储(Java)

    JDK1.8中JVM把String常量池移入了堆中,同时取消了“永久代”,改用元空间代替(Metaspace)java中对String对象特殊对待,所以在heap区域分成了两块,一块是字符串常量池(S ...

  6. 【Java】运行时Java对象在内存中是如何存储的?

    翻译自这一篇文章 我们知道函数在内存中实现为一个活动记录的栈.我们也知道Java方法在JVM栈区中实现为一个帧栈而Java对象是在堆区进行分配的. Java对象在堆内存中是怎样的呢?一旦对象保存在内存 ...

  7. 数据在内存中的存储方式( Big Endian和Little Endian的区别 )(x86系列则采用little endian方式存储数据)

    https://www.cnblogs.com/renyuan/archive/2013/05/26/3099766.html 1.故事的起源 “endian”这个词出自<格列佛游记>.小 ...

  8. Java程序在内存中运行详解

    目录 Java程序在内存中运行详解 一.JVM的内存分布 二.程序执行的过程 三.只有一个对象时的内存图 四.两个对象使用同一个方法的内存图 五.两个引用指向同一个对象的内存图 六.使用对象类型作为方 ...

  9. Java变量以及内存分配

    Java变量以及内存分配(非常重要) 堆栈 静态存储区域 一个由C/C++编译的程序占用的内存分为以下几个部分 1.栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.其操 ...

随机推荐

  1. ajax结合sweetalert实现删除按钮动态效果

    目录 一.ajax结合sweetalert实现删除按钮动态效果 二.bulk_create批量插入数据 1. 一条一条插入 2. 批量插入 三.自定义分页器 一.ajax结合sweetalert实现删 ...

  2. 《Dotnet9》系列-开源C# WPF控件库1《MaterialDesignInXAML》强力推荐

    时间如流水,只能流去不流回! 点赞再看,养成习惯,这是您给我创作的动力! 本文 Dotnet9 https://dotnet9.com 已收录,站长乐于分享dotnet相关技术,比如Winform.W ...

  3. Springboot 项目源码 Activiti6 工作流 vue.js html 跨域 前后分离 websocket即时通讯

    特别注意: Springboot 工作流  前后分离 + 跨域 版本 (权限控制到菜单和按钮) 后台框架:springboot2.1.2+ activiti6.0.0+ mybaits+maven+接 ...

  4. 微信公众号:Mysticbinary

    愿你有绝对自由.每周会写一篇哲学类文章.

  5. PromiseKit基本使用及源码解析

    Promise处理一系列异步操作的应用框架,能够保证顺序执行一系列异步操作,当出错时可以通过catch捕获错误进行处理.Promise框架也是很好的诠释了swift的面相协议编程以及函数式编程 两种类 ...

  6. 仿Inshot分享页图片圆形展开缩放动画

    版权声明:本文为xing_star原创文章,转载请注明出处! 本文同步自http://javaexception.com/archives/221 圆形展开缩放动画 关键代码: final Anima ...

  7. Nginx核心流程及模块介绍

    Nginx核心流程及模块介绍 1. Nginx简介以及特点 Nginx简介: Nginx (engine x) 是一个高性能的web服务器和反向代理服务器,也是一个IMAP/POP3/SMTP服务器 ...

  8. PHP最新面试题2019

    1.字符串"0"在PHP和js中转换为布尔值是false还是true php:false;  php 弱语言 '0'和0一样: js:true:字符串除了空字符串('')其他都是t ...

  9. Zabbix-(二) 使用docker部署

    Zabbix-(二)使用docker部署 一.前言 前文记录了在服务器上搭建zabbix平台,本文记录使用docker部署zabbix 4.4 准备 Centos7.6 虚拟机,并安装了docker ...

  10. MySql 更新死锁问题 Deadlock found when trying to get lock; try restarting transaction

    文章导航-readme MySql 更新死锁问题 Deadlock found when trying to get lock; try restarting transaction 1.场景 //t ...