文档章节

类加载机制

Vincent-Duan
 Vincent-Duan
发布于 2016/10/24 22:40
字数 765
阅读 6
收藏 0

首先看一段代码,想想下面的代码输出结果是什么:

/**
 * 
 * @author vincent_duan
 * 
 */
public class LoadingTest {
    public static LoadingTest obj = new LoadingTest();
    public static int val1;
    public static int val2=0;

    public LoadingTest() {
        val1 = 10;
        val2 = val1;
        System.out.println("before val1->" + val1);
        System.out.println("before val2->" + val2);
    }
    

    public static void main(String[] args) {
        System.out.println("after val1->"+val1);
        System.out.println("after val2->"+val2);
    }
}

程序输出如下:

before val1->10
before val2->10
after val1->10
after val2->0

上述代码示例中,如果大家不信心的话,肯定会认为在main()方法中打印的Loading类的静态变量val1和val2的值都为10;但实际上程序最终输出的结果却是val1等于10,而val2等于0。在Loading类的构造方法中,尽管已经将静态变量val1和val2都显式赋值为10了,并且在构造方法中所打印的结果也的确为10,那么为什么会与main()方法中输出的结果不一致呢?

如果将上述代码的位置稍作调整后,程序最终的输出结果是否又会产生变化呢?

public static int val1;
public static int val2=0;
public static LoadingTest obj = new LoadingTest();

程序输出如下:

before val1->10
before val2->10
after val1->10
after val2->10

将声明静态变量obj的代码位置放在声明静态变量val2之后,程序最终的输出结果就跟预期的值一致了,这又是为什么呢?简单来说,当类加载器将Loading类加载进JVM内部后,会在方法区中生成一个与该类型对应的java.lang.Class对象实例,当进入到准备阶段时,JVM便会为Loading类中的3个静态变量分配内存空间,并为其设置初始值(val1和val2的初始值为0,而obj的初始值为null)。当经历到类加载过程中的初始化阶段时,程序最终的输出结果就会和代码的执行顺序有关了。在第一段代码中,静态变量obj是优先初始化的,那么JVM将会执行到其构造方法中,并覆盖掉静态变量val1和val2之前持有的初始值,也就是说,初始化静态变量obj后,val1和val2所持有的值都是10.接下来JVM会检查静态变量val1是否也需要执行初始化,由于val1并没有显示地指定进行赋值操作,因此将会直接跳转到静态变量val2上,这里就非常关键了。尽管之前指定了value2所持有的值为10,但当执行到val2=0时等于又重新对静态变量val2显式执行了一次赋值操作,也就是说,当前赋值操作将会覆盖掉之前在构造方法中的复制操作,这就是为什么val2的输出结果为0,而非10的原因。在将代码的执行顺序进行调换,尽管val2同样也经历过2次赋值操作,但最后一次赋予的值却是10,所以程序最终的输出结果就跟预期一致。

© 著作权归作者所有

Vincent-Duan

Vincent-Duan

粉丝 33
博文 430
码字总数 237992
作品 0
海淀
私信 提问

暂无文章

Android 图片加载带进度条的ImageView

https://blog.csdn.net/shu_quan/article/details/79975578

shzwork
4分钟前
2
0
关于XAMPP默认端口80 和443被占用的问题

本文转载于:专业的前端网站➩关于XAMPP默认端口80 和443被占用的问题 关于安装xampp-win32-1.8.1-VC9-installer.zip后启动时候报端口80和443被占用的问题解决 xampp-win32-1.8.1-VC9-instal...

前端老手
6分钟前
2
0
错误Setting the parent of a transform which resides in a Prefab Asset is...

错误日志 Setting the parent of a transform which resides in a Prefab Asset is disabled to prevent data corruption 原因1 用Resouce.Load加载一个prefab,没有实例化直接设置parent ......

XBlock
6分钟前
2
0
Spring boot 配置mybatis

当然任何模式都需要首先引入mybatis-spring-boot-starter的pom文件,现在最新版本是1.1.1(刚好快到双11了 :)) <dependency>    <groupId>org.mybatis.spring.boot</groupId>    <......

雷开你的门
7分钟前
4
0
云栖干货回顾 | 更强大的实时数仓构建能力!分析型数据库PostgreSQL 6.0新特性解读

阿里云 AnalyticDB for PostgreSQL 为采用MPP架构的分布式集群数据库,完备支持SQL 2003,部分兼容Oracle语法,支持PL/SQL存储过程,触发器,支持标准数据库事务ACID。AnalyticDB PG通过行存...

开源中国小二
19分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部