`

Java程序员从笨鸟到菜鸟之(九十四)深入java虚拟机(三)——类的生命周期(下)类的初始化

阅读更多


 

上接深入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程序员-从笨鸟到菜鸟.pdf

    java程序员-从笨鸟到菜鸟.pdf

    [网盘]java程序员由菜鸟到笨鸟.pdf

    ### Java程序员成长之路——从菜鸟到笨鸟 #### 一、引言 《Java程序员由菜鸟到笨鸟》是一本由曹胜欢编写的书籍,旨在帮助初学者掌握Java编程的基础知识,并逐步进阶至更高级的应用场景。本书不仅适合初学者作为...

    JAVA程序员 从笨鸟到菜鸟.pdf

    曹胜欢在《JAVA程序员 从笨鸟到菜鸟.pdf》中分享了他个人学习Java的经历,从迷茫到逐渐成长的过程。他强调了自学的重要性,并鼓励初学者不要怕走弯路,同时希望自己的经验可以帮助到同样在学习Java的初学者。 2. ...

    Java程序员由菜鸟到笨鸟学习文档

    Java程序员的成长之路是一个充满挑战与探索的过程,从初学者到熟练掌握各项技能,需要系统性的学习和实践。"Java程序员由菜鸟到笨鸟学习文档"就是这样一个旨在帮助初入Java世界的学习者逐步进阶的资源。它覆盖了从...

    《Java程序员-从笨鸟到菜鸟》PDF下载

    资源名称:《Java程序员-从笨鸟到菜鸟》PDF 下载资源目录:作者简介:..........................................................................................................................................

    java程序员由菜鸟到笨鸟

    《java程序员由菜鸟到笨鸟》 刚开始学习java时看过的一个学习资料。 其中包括开发环境搭建、面向对象、Javascript、设计模式、SSH、jquery、java虚拟机等内容。 设计内容较广,可以学习参考。

    [网盘]java程序员由菜鸟到笨鸟.pdf.2018_03_19

    根据提供的文件信息,“Java程序员由菜鸟到笨鸟”是一本旨在帮助初学者成长为合格Java开发者的书籍。本书作者为曹胜欢,发布日期为2018年3月19日。下面将从多个角度对本书涉及的重要知识点进行概述。 ### 一、Java...

    [网盘]java程序员由菜鸟到笨鸟.pdf.2018_03_17

    根据提供的文件信息,“Java程序员由菜鸟到笨鸟”是一本旨在帮助初学者成长为合格Java开发者的书籍。本书作者为曹胜欢,发布日期为2018年3月17日。以下是从该书的标题、描述以及部分可能包含的内容中提炼出的关键...

    黑马程序员-Java语言进阶-源码、教程笔记.zip

    day01_Object类、常用API day02_Collection、泛型 day03_List、Set、数据结构、Collections day04_Map,斗地主案例 day05_异常,线程 day06_线程、同步 day07_等待与唤醒案例、线程池、Lambda表达式 day08_File类、...

    java游戏笨鸟

    《Java游戏:笨鸟》(也称为FlappyBird)是一款基于Java编程语言开发的简单游戏,旨在帮助初学者更好地理解和掌握Java编程基础。这款游戏的实现涉及了许多Java编程的关键概念和技术,下面将对这些知识点进行详细阐述...

Global site tag (gtag.js) - Google Analytics