首先需要明白以下几点:

  1. 栈空间(stack),连续的存储空间,遵循后进先出的原则,用于存放局部变量
  2. 堆空间(heap),不连续的空间,用于存放new出的对象,或者说是类的实例。
  3. 方法区(method),方法区在堆空间内,用于存放①类的代码信息;②静态变量和方法;③常量池(字符串敞亮等,具有共享机制)。
  4. Java中除了基本数据类型,其他的均是引用类型,包括类、数组等等。
  5. 数据类型的默认值

    基本数据类型默认值:

    数值型:0

    浮点型:0.0

    布尔型:false

    字符型:\u0000

    引用类型:null
  6. 变量初始化

    成员变量可不初始化,系统会自动初始化;

    局部变量必须由程序员显式初始化,系统不会自动初始化。

实例进行分析。

创建类

分别是Student、Computer、Test,代码如下:

public class Student {

	int score;
int age;
String name; Computer computer; public void study() { System.out.println("studying...");
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
public class Computer {
int price;
String brand;
}
  • 1
  • 2
  • 3
  • 4
public class Test {

	public static void main(String[] args) {

		Student stu = new Student();

		stu.name = "xiaoming";

		stu.age = 10;

		stu.study();

		Computer c = new Computer();
c.brand = "Hasse"; System.out.println(c.brand); stu.computer = c;
System.out.println(stu.computer.brand); // System.out.println("----------------------------------------");
//
// c.brand = "Dell";
//
// System.out.println(c.brand);
// System.out.println(stu.computer.brand);
//
// System.out.println(stu.computer.brand == c.brand); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

代码分析

我们知道,程序的入口是main(),因而从main方法从上到下、从左到右进行分析。

Student stu = new Student();

①首先,Java虚拟机(JVM)去方法区寻找是否有Test类的代码信息,如果存在,直接调用。如果没有,通过类加载器(ClassLoader)把.class字节码加载到内存中,并把静态变量和方法、常量池加载(“xiaoming”、“Hasse”)。

②走到Student,以同样的逻辑对Student类进行加载;静态成员;常量池(“studying”)。

③走到stu,stu在main方法内部,因而是局部变量,存放在栈空间中。

④走到new Student,new出的对象(实例),存放在堆空间中,以方法区的类信息为模板创建实例。

⑤‘’=‘’赋值操作,把new Student的地址告诉stu变量,stu通过四字节的地址(十六进制),引用该实例。

如下图:

stu.name = “xiaoming”;

⑥stu通过引用new Student实例的name属性,该name属性通过地址指向常量池的"xiaoming"敞亮。

stu.age = 10;

⑦s实例的age属性是基本数据类型,基本数据类型直接赋值。

stu.study();

⑧调用实例的方法时,并不会在实例对象中生成一个新的方法,而是通过地址指向方法区中类信息的方法。

⑥⑦⑧的过程如下图:

Computer c = new Computer();

同stu变量的生成过程。

c.brand = “Hasse”;

同stu.name = "xiaoming"过程。

stu.computer = c;

⑨把c对象对Computer实例的引用赋值给Student实例的computer属性。亦即:该Student实例的computer属性指向该Computer类的实例。

如下图:


拓展

改变brand的地址指向。

为进一步理解,我们把注释内容去掉:

⑨重新将Computer实例的brand属性指向"Dell"常量,那stu.computer.brand指向谁呢?Dell还是Hasse?

c.brand = "Dell";
  • 1

根据刚才的分析可知:

stu通过地址引用Student实例,而该实例的computer的指向和c的指向是同一个Computer实例,因而改变该Computer实例的brand属性的指向,两者都会改变。

举个例子:

访问大明,和访问大明的儿子的爸爸,实质上访问的是同一个对象:大明。

因而,最终的结果是true。

理解字符串常量及常量池

下面我们添加新的代码,如下:

		String str = "Dell";
System.out.println(c.brand == str);
  • 1
  • 2

结果会如何呢?

根据常量池具有共享性,可知并不会生成新的常量"Dell",而是会把str通过地址指向原来的"Dell",因而结果是true。

Java学习1:图解Java内存分析详解(实例)的更多相关文章

  1. Java学习笔记 线程池使用及详解

    有点笨,参考了好几篇大佬们写的文章才整理出来的笔记.... 字面意思上解释,线程池就是装有线程的池,我们可以把要执行的多线程交给线程池来处理,和连接池的概念一样,通过维护一定数量的线程池来达到多个线程 ...

  2. java 堆栈内存分析详解

    计算机术语里面堆和栈代表不同的存储结构:stack-栈:heap-堆 所以java虚拟机(JVM)中堆和栈是两种内存 堆.栈对比 对比点 堆 栈 JVM中的功能 内存数据区 内存指令区 动静态 运行时 ...

  3. 1.4(java学习笔记) 面向对象内存分析

      首先介绍几个概念 栈: 1.栈是方法执行的内存模型,每调用一个方法都会创建一个栈帧. 2.jvm为每个线程创建一个栈,存放方法相关信息,栈属于线程私有不共享. 3.栈由系统自动分配,是连续的内存空 ...

  4. java学习(二)多态中成员变量详解

    今天我总结了一下java多态中成员变量的赋值与调用 举一个我当初做过的小案例: class Fu{ int num; void show(){} } class Zi extends Fu{ //in ...

  5. Java学习之二维数组定义与内存分配详解

    二维数组:就是元素为一维数组的一个数组. 格式1: 数据类型[][] 数组名 = new 数据类型[m][n]; m:表示这个二维数组有多少个一维数组. n:表示每一个一维数组的元素有多少个. 注意: ...

  6. 零拷贝详解 Java NIO学习笔记四(零拷贝详解)

    转 https://blog.csdn.net/u013096088/article/details/79122671 Java NIO学习笔记四(零拷贝详解) 2018年01月21日 20:20:5 ...

  7. java程序运行时内存分配详解

    java程序运行时内存分配详解 这篇文章主要介绍了java程序运行时内存分配详解 ,需要的朋友可以参考下   一. 基本概念 每运行一个java程序会产生一个java进程,每个java进程可能包含一个 ...

  8. Java内存结构详解

    Java内存结构详解 Java把内存分成:栈内存,堆内存,方法区,本地方法区和寄存器等. 下面分别介绍栈内存,堆内存,方法区各自一些特性: 1.栈内存 (1)一些基本类型的变量和对象的引用变量都是在函 ...

  9. 云时代架构阅读笔记六——Java内存模型详解(二)

    承接上文:云时代架构阅读笔记五——Java内存模型详解(一) 原子性.可见性.有序性 Java内存模型围绕着并发过程中如何处理原子性.可见性和有序性这三个特征来建立的,来逐个看一下: 1.原子性(At ...

随机推荐

  1. 一、Windows部署RabbitMQ

    RabbitMQ官方网站非常详细,以下只是本人学习过程的整理 一.Windows部署RabbitMQ:https://www.cnblogs.com/yangleiyu/p/15539618.html ...

  2. Java 中控制执行流程

    if-else 非常常用的流程控制非 if-else 莫属了,其中 else 是可选的,if 有两种使用方式 其一: if (Boolean-expression) { statement; } 其二 ...

  3. [bzoj1303]中位数图

    由于是排列,因此b一定只出现了一次,找到出现的位置并向左右扩展考虑如何判定是否满足条件,当且仅当$[左边比b小的数ls]+[右边比b小的数rs]=[左边比b大的数lb]+[右边比b大的数rb]$,暴力 ...

  4. [bzoj1005]明明的烦恼

    根据purfer序列的原理,每一个purfer序列都一一对应了一棵树,每一个点在purfer序列中出现的次数就是它的度数,那么直接用组合数去计算即可,注意要加高精度 1 #include<cst ...

  5. Electron快速入门之事件

    const { app, BrowserWindow } = require('electron') function createWindow () {   const win = new Brow ...

  6. [IIS]发布到 IIS 上的程序没有权限访问共享文件

    老板突然跑路了,丢下一个破项目让我一个人维护,各种奇葩问题不断. 为了弄一键发布,布置了新的环境,结果新环境下的程序不能访问共享文件了. 访问共享文件需要设置应用程序池(Application Poo ...

  7. 未能加载文件或程序集“Microsoft.CodeDom.Providers.DotNetCompilerPlatform

    "/"应用程序中的服务器错误. 未能加载文件或程序集"Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Versio ...

  8. Java二次开发海康SDK-对接门禁机

    写在最前 SDK版本:CH-HCNetSDKV6.1.6.45_build20210302_win64 参考文档:海康SDK使用手册_V6.1 对接测试设备型号:DS-K1T671M 设备序列号:E5 ...

  9. Ubuntu 18.04 WMware 编译 AOSP android-7.1.2_r33 笔记

    0 前言 问:都快2022年了,为什么还要编译 android 7.1.2 ? 答:某脱壳机特征修改或移植到其他机型(此处省略1000字...) 笔者在编译之前并没有加入专有二进制文件(后续加入了再补 ...

  10. 更通俗的理解JS原型链

    最近在网上看到一篇理解原型链的,感觉非常好非常通俗易懂,拿来记录一下~: 1)人是人他妈生的,妖是妖他妈生的.人和妖都是对象实例,而人他妈和妖他妈就是原型.原型也是对象,叫原型对象. 2)人他妈和人他 ...