看起来很懵的java内存加载面试题
源代码如下,求结果
public class MemoryAnalyse {
public static int k = 0;
public static MemoryAnalyse t1 = new MemoryAnalyse("t1");
public static MemoryAnalyse t2 = new MemoryAnalyse("t2");
public static int i = print("i");
public static int j = print("j");
public static int n = 99;
{
print("constructor code");
}
static {
print("static code");
}
public static int print(String s) {
System.out.println("i=" + i + " " + s + " k=" + k + " n=" + n
+ " j=" + j);
++i;
++k;
++n;
return i;
}
public MemoryAnalyse(String string) {
print(string);
}
public static void main(String[] args) throws ClassNotFoundException {
MemoryAnalyse d = new MemoryAnalyse("T");
}
}
然而结果是这个
i=0 constructor code k=0 n=0 j=0
i=1 t1 k=1 n=1 j=0
i=2 constructor code k=2 n=2 j=0
i=3 t2 k=3 n=3 j=0
i=4 i k=4 n=4 j=0
i=5 j k=5 n=5 j=0
i=6 static code k=6 n=99 j=6
i=7 constructor code k=7 n=100 j=6
i=8 T k=8 n=101 j=6
有没有很惊讶,结果竟然这么复杂.好,下面我们分析一下,在分析之前,先普及下不怎么用的基础知识
代码块和静态代码块何时运行问题:
代码块在创建对象时运行
静态代码块在类加载时运行
大家都知道static是属于类的并非对象,也就是说static修饰的东西都会在class加载到方法区时就存在在那里.所以方法区中类加载时内存过程如下
1.当类刚加载时会全部加载到方法区时,此时所有变量全部未实例化.

2.实例化参数t1

此时因为代码块在创建对象时执行,且在构造函数之前执行,所以先执行代码块
{
print("constructor code");
}
因为此时所有的变量都为默认值,所以执行后打印结果为
i=0 constructor code k=0 n=0 j=0
此时i,n,k的值都已经自加一,值为1
然后实例化调用构造函数
public MemoryAnalyse(String string) { //这里string为t1
print(string);
}
构造函数调用结果如下
i=1 t1 k=1 n=1 j=0
此时i,n,k的值都已经自加一,值为2
3.实例化参数t2

和第一步一样在构造函数之前执行代码块
{
print("constructor code");
}
i=2 constructor code k=2 n=2 j=0
此时i,n,k的值都已经自加一,值为3
然后实例化调用构造函数
public MemoryAnalyse(String string) { //这里string为t2
print(string);
}
构造函数调用结果如下
i=3 t2 k=3 n=3 j=0
此时i,n,k的值都已经自加一,值为4
4.初始化参数i

这里直接调用print("i")函数,得到结果为
i=4 i k=4 n=4 j=0
此时i,k,j值为5,注意i的值不是通过自加一变成5的,而是通过函数的返回值赋给i的
5.初始化参数j

这里和上一步一样,执行print("j"),然后把函数的返回值赋给j,打印结果为
i=5 j k=5 n=5 j=0
此时j的值已经为6
到这里类加载的内部参数变化就完成了,我们可以用加载类的方式调用一下
public static void main(String[] args) throws ClassNotFoundException {
//MemoryAnalyse d = new MemoryAnalyse("T");
Class.forName("MemoryAnalyse");
}
Class.forName(类名字符串)是手动加载类到方法区,得到结果为
i=0 constructor code k=0 n=0 j=0
i=1 t1 k=1 n=1 j=0
i=2 constructor code k=2 n=2 j=0
i=3 t2 k=3 n=3 j=0
i=4 i k=4 n=4 j=0
i=5 j k=5 n=5 j=0
i=6 static code k=6 n=99 j=6 //这行的出现是因为static代码段在类加载时执行.n=99是因为类加载了,n的初值为99把之前的值覆盖掉了
然后改为我们之前的demo
public static void main(String[] args) throws ClassNotFoundException {
MemoryAnalyse d = new MemoryAnalyse("T");
//Class.forName("MemoryAnalyse");
}
执行结果为
i=0 constructor code k=0 n=0 j=0 //t1代码块执行
i=1 t1 k=1 n=1 j=0 //t1构造函数执行
i=2 constructor code k=2 n=2 j=0 //t2代码块执行
i=3 t2 k=3 n=3 j=0 //t2构造函数执行
i=4 i k=4 n=4 j=0
i=5 j k=5 n=5 j=0
i=6 static code k=6 n=99 j=6 //静态代码块执行
i=7 constructor code k=7 n=100 j=6 //T代码块执行
i=8 T k=8 n=101 j=6 //T构造函数执行
最后两行的出现就很简单了,一个是代码块的,一个是构造函数的
这么一分析是不是简单了很多
看起来很懵的java内存加载面试题的更多相关文章
- 很考验人的java内存加载面试题
源代码如下,求结果 public class MemoryAnalyse { public static int k = 0; public static MemoryAnalyse t1 = new ...
- java内存加载机制
什么是java类加载? 类加载是指将.class类中的二进制数据存放到内存中,会在内存中的推中建立一个java.lang.String的引用对象来存放方法区的数据结构,而类中的数据会放到方法区中 类加 ...
- 【设计模式】C++单例模式的几种写法——Java自动加载内部类对象,C++怎么破?
单例模式是最简单的设计模式,就让我像玩简单的游戏一样写下去吧. v1: 简单模式 和这个版本有过一面之缘,但不敢苟同. class Singleton { private: Singleton() { ...
- 原来热加载如此简单,手动写一个 Java 热加载吧
1. 什么是热加载 热加载是指可以在不重启服务的情况下让更改的代码生效,热加载可以显著的提升开发以及调试的效率,它是基于 Java 的类加载器实现的,但是由于热加载的不安全性,一般不会用于正式的生产环 ...
- Java动态加载类
详见:https://blog.csdn.net/zai_xia/article/details/80026325 扩展:java反射机制与动态加载类 https://www.cnblogs.com/ ...
- java class加载机制及对象生成机制
java class加载机制及对象生成机制 当使用到某个类,但该类还未初始化,未加载到内存中时会经历类加载.链接.初始化三个步骤完成类的初始化.需要注意的是类的初始化和链接的顺序有可能是互换的. Cl ...
- 内存加载DLL
1.前言 目前很多敏感和重要的DLL(Dynamic-link library) 都没有提供静态版本供编译器进行静态连接(.lib文件),即使提供了静态版本也因为兼容性问题导致无法使用,而只提供DLL ...
- Java虚拟机加载类
Java虚拟机是如何加载Java类的 Java虚拟机加载Java类总共需要经过3步:加载-----链接-----初始化.Java语言的类型可以分为两大类:基本类型和引用类型.基本类型是有Java虚拟机 ...
- Java ClassLoader加载机制理解
今天看到了一篇介绍Java ClassLoader加载机器的文章, 才发觉一直来自己的肤浅, 好好地给补了一课, 不得不存档! 原文地址: http://www.blogjava.net/lhulcn ...
随机推荐
- P4555 [国家集训队]最长双回文串
P4555 [国家集训队]最长双回文串 manacher 用manacher在处理时顺便把以某点开头/结尾的最长回文串的长度也处理掉. 然后枚举. #include<iostream> # ...
- P4001 [BJOI2006]狼抓兔子(对偶图)
P4001 [BJOI2006]狼抓兔子 最短路+对偶图 看这题最容易想到的就是网络流.Dinic可以过,据说还跑得比正解快. 如果不写网络流,那么需要知道2个前置知识:平面图和对偶图(右转baidu ...
- 【angular2+typeScript+ng-zorro】Carousel 走马灯的左右方向控件实现
ng-zorro Carousel 走马灯的左右方向控件实现 ng-zorro框架的走马灯本身还没有左右方向控件的实现,作者只是在文档中(0.6x)中曝出几个方法接口,如图: 实现: 在根compon ...
- Python3基础 file with 配合文件操作
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...
- 51Nod 1344 走格子(贪心
1344 走格子 有编号1-n的n个格子,机器人从1号格子顺序向后走,一直走到n号格子,并需要从n号格子走出去.机器人有一个初始能量,每个格子对应一个整数A[i],表示这个格子的能量值.如果A[i ...
- vuejs全局api概念
什么是全局API? 全局API并不在构造器里,而是先声明全局变量或者直接在Vue上定义一些新功能,Vue内置了一些全局API,比如我们今天要学习的指令Vue.directive.说的简单些就是,在构造 ...
- 常用字符与ASCII代码对照表
常用字符与ASCII代码对照表 为了便于查询,以下列出ASCII码表:第128-255号为扩展字符(不常用) ASCII码 键盘 ASCII 码 键盘 ASCII 码 键盘 ASCII 码 键盘 27 ...
- HDU 3549 Flow Problem(最大流模板)
http://acm.hdu.edu.cn/showproblem.php?pid=3549 刚接触网络流,感觉有点难啊,只好先拿几道基础的模板题来练练手. 最大流的模板题. #include< ...
- Java中关于Arrays.asList()的操作
我们可以通过Arrays.asList() 产生一个List,但是要记住,我们通过Arrays.asList产生的list是基于一个固定大小的数组的, 仅支持那些不会改变数组大小的操作.所以我们在使用 ...
- 基于贝叶斯优化的超参数tuning
https://arimo.com/data-science/2016/bayesian-optimization-hyperparameter-tuning/ 贝叶斯优化:使用高斯过程作为代理函数, ...