上接深入java
虚拟机
——
深入java虚拟机(二)——类加载器详解(上)
,在上一篇文章中,我们讲解了类的生命周期的加载和连接,这一篇我们接着上面往下看。
类的初始化
:
在类的生命周期执行完加载和连接之后就开始了类的初始化。在类的初始化阶段,
java
虚拟机执行类的初始化语句,为类的静态变量赋值,在程序中,类的初始化有两种途径:(
1
)在变量的声明处赋值。(
2
)在静态代码块处赋值,比如下面的代码,
a
就是第一种初始化,
b
就是第二种初始化
public class Test
{
public static int a = 0;
public static int b ;
static{
b=2;
}
}
静态变量的声明和静态代码块的初始化都可以看做静态变量的初始化,类的静态变量的初始化是有顺序的。顺序为类文件从上到下进行初始化,想到这,想起来
一个很无耻的面试题
,分享给大家看一下:
package com.bzu.csh;
class Singleton
{
private static Singleton singleton = new Singleton();
public static int counter1;
public static int counter2 = 0;
private Singleton()
{
counter1++;
counter2++;
}
public static Singleton getInstance()
{
return singleton;
}
}
public class Test
{
public static void main(String[] args)
{
Singleton singleton = Singleton.getInstance();
System.out.println("counter1 = " + singleton.counter1);
System.out.println("counter2 = " + singleton.counter2);
}
}
大家先看看这里的程序会输出什么?
不知道大家的答案是什么,如果不介意的话可以把你的答案写到评论上,看看有多少人的答案和你一样的。我先说说我刚开始的答案吧。我认为会输出:
counter1=1
Counter2= 1
不知道大家的答案是不是这个,反正我的是。下面我们来看一下正确答案:
不知道你做对没有,反正我刚开始做错了。好,现在我来解释一下为什么会是这个答案。在给出解释之前,我们先来看一个概念:
Java程序对类的使用方式可分为两种
主动使用
被动使用
•所有的Java虚拟机实现必须在每个类或接口被Java程序“
首次主动使用
”
时才初始化他们
主动使用(六种)
–创建类的实例
–访问某个类或接口的静态变量,或者对该静态变量赋值
–调用类的静态方法
–反射(如Class.forName(“com.bzu.csh.Test”))
–初始化一个类的子类
–Java虚拟机启动时被标明为启动类的类(JavaTest)
OK,我们开始解释一下上面的答案,程序开始运行,首先执行
main
方法,执行
main
方法第一条语句,调用
Singleton类的静态方法,这里调用Singleton类的静态方法就是主动使用Singleton类。所以开始加载Singleton类。在加载Singleton类的过程中,首先对静态变量赋值为默认值,
Singleton=null
counter1=0
Counter2=0
给他们赋值完默认值值之后,要进行的就是对静态变量初始化,对声明时已经赋值的变量进行初始化。我们上面提到过,初始化是从类文件从上到下赋值的。所以首先给Singleton
赋值,给它赋值,就要执行它的构造方法,然后执行
counter1++;counter2++;
所以这里的
counter1=1;counter2=1;
执行完这个初始化之后,然后执行
counter2
的初始化,我们声明的时候给他初始化为
0
了,所以
counter2
的值又变为了
0.
初始化完之后执行输出。所以这是的
counter1=1
counter2=0
类初始化步骤
(1)假如一个类还没有被加载或者连接,那就先加载和连接这个类
(2)假如类存在直接的父类,并且这个父类还没有被初始化,那就先初始化直接的父类
(3)假如类中存在初始化语句,那就直接按顺序执行这些初始化语句
在上边我们我们说了java
虚拟机实现必须在每个类或接口被Java程序“首次主动使用
”
时才初始化他们,上面也举出了六种主动使用的说明。除了上述六种情形,其他使用Java类的方式都被看作是被动使用,不会导致类的初始化。程序中对子类的“主动使用”会导致父类被初始化;但对父类的“主动”使用并不会导致子类初始化(不可能说生成一个Object类的对象就导致系统中所有的子类都会被初始化)
注:
调用ClassLoader类的loadClass方法加载一个类,并不是对类的主动使用,不会导致类的初始化。
当java虚拟机初始化一个类时,要求它的所有的父类都已经被初始化,但这条规则并不适用于接口。
在初始化一个类时,并不会先初始化它所实现的接口
在初始化一个接口时,并不会先初始化它的父接口
因此,一个父接口并不会因为它的子接口或者实现类的初始化而初始化。只有当程序首次使用特定接口的静态变量时,才会导致该接口的初始化。只有当程序访问的静态变量或静态方法确实在当前类或当前接口中定义时,才可以认为是对类或接口的主动使用。如果是调用的子类的父类属性,那么子类不会被初始化。
分享到:
相关推荐
JAVA程序员 从笨鸟到菜鸟
java程序员-从笨鸟到菜鸟.pdf
自学道路上的迷惑,所以从2012 年2 月份开始着手《java 程序员从笨鸟 到菜鸟》的编写。真心希望可以帮助刚起步学习java 开发的兄弟姐妹们。 没参与过中大型项目的开发,没有高的学历。所以此人之书只能供参考。
摘要视图订阅曹胜欢欢迎关注微信账号:java那些事:csh624366188.每天一篇java相关的文章登录 | 注册学习专区(140)Java程序员从笨鸟到菜
java程序员由菜鸟到笨鸟 作者:曹胜欢
java比较好的一篇文档,作者写的比较细,主要是一些基础概念说的比较细。
本电子书涵盖了从java基础到javaweb开放框架的大部分内容。在编写的过程中,难免会出现一些错误,希望大家能多多提些意见。
资源名称:《Java程序员-从笨鸟到菜鸟》PDF 下载资源目录:作者简介:..........................................................................................................................................
摘要视图订阅曹胜欢欢迎关注微信账号:java那些事:csh624366188.每天一篇java相关的文章登录 | 注册学习专区(140)Java程序员从笨鸟到菜
《java程序员由菜鸟到笨鸟》 刚开始学习java时看过的一个学习资料。 其中包括开发环境搭建、面向对象、Javascript、设计模式、SSH、jquery、java虚拟机等内容。 设计内容较广,可以学习参考。
摘要视图订阅曹胜欢欢迎关注微信账号:java那些事:csh624366188.每天一篇java相关的文章登录 | 注册Java程序员从笨鸟到菜鸟(81)学习专区
java程序员由菜鸟到笨鸟 作者:曹胜欢
摘要视图订阅曹胜欢欢迎关注微信账号:java那些事:csh624366188.每天一篇java相关的文章登录 | 注册学习专区(140)Java程序员从笨鸟到菜
java程序员由菜鸟到笨鸟 作者:曹胜欢