`

类的装载、连接与初始化 -- 纠正

阅读更多
1.首先纠正<<深入java虚拟机>>电子书中的一个小错误(针对父类和子类拥有共同static变量时),那么父类和子类static变量,static块都会初始化。
 







-------------------------
class NewParent {  
  
    static int hoursOfSleep = (int) (Math.random() * 3.0);  
  
    static {  
        System.out.println("NewParent was initialized.");  
    }  
}  

class NewbornBaby extends NewParent {  
  
    static int hoursOfCrying = 6 + (int) (Math.random() * 2.0);  
  
    static {  
        System.out.println("NewbornBaby was initialized.");  
    }  
}  

class Example2 {  
    public static void main(String[] args) {  
        int hours = NewbornBaby.hoursOfSleep; 
        System.out.println(hours);  
    }  
  
    static {  
        System.out.println("Example2 was initialized.");  
    }  
}  

会输出:
Example2 was initialized.
NewParent was initialized.
2

如果是 int hours = NewbornBaby. hoursOfCrying ;
Example2 was initialized.
NewParent was initialized.
NewbornBaby was initialized.
2

如果
class NewParent {  
  
    static int hoursOfSleep = (int) (Math.random() * 3.0);  
  
    static {  
        System.out.println("NewParent was initialized.");  
    }  
}  

class NewbornBaby extends NewParent {  
  
    static int hoursOfSleep = 6 + (int) (Math.random() * 2.0);  
  
    static {  
        System.out.println("NewbornBaby was initialized.");  
    }  
}  

class Example2 {  
    public static void main(String[] args) {  
       [b] int hours = NewbornBaby.hoursOfSleep;  [/b][color=red][/color]
        System.out.println(hours);  
    }  
  
    static {  
        System.out.println("Example2 was initialized.");  
    }  
}  
会输出:
Example2 was initialized.
NewParent was initialized.
NewbornBaby was initialized.
2

------------------------------------


#######################################

2. 对类的加载、连接和初始化用Visio做了下整理,和大家一起讨论吧。









  • 大小: 149.4 KB
  • 大小: 42.8 KB
  • 大小: 66 KB
  • 大小: 100.9 KB
  • 大小: 156.7 KB
  • 大小: 177.3 KB
分享到:
评论
20 楼 gstarwd 2010-07-29  
JE的代码编辑器貌似有问题  不能过滤UBB标签
19 楼 bugmenot 2010-07-03  
maozj 写道
首先纠正<<深入java虚拟机>>电子书中的一个小错误(针对父类和子类拥有共同static变量时),那么父类和子类static变量,static块都会初始化。

楼主大大修改后主楼的描述还是容易误导咱小的呀。修改后第二版本代码,也就是
class NewParent {     
     
    static int hoursOfSleep = (int) (Math.random() * 3.0);     
     
    static {     
        System.out.println("NewParent was initialized.");     
    }     
}     
  
class NewbornBaby extends NewParent {     
     
    static int hoursOfSleep = 6 + (int) (Math.random() * 2.0);     
     
    static {     
        System.out.println("NewbornBaby was initialized.");     
    }     
}     
  
class Example2 {     
    public static void main(String[] args) {     
        int hours = NewbornBaby.hoursOfSleep;
        System.out.println(hours);     
    }     
     
    static {     
        System.out.println("Example2 was initialized.");     
    }     
}

NewParent.hoursOfSleep与NewbornBaby.hoursOfSleep只是同名,却是两个完全独立的变量,本质上说跟一个叫abc另一个叫def一样。
父子类里同名变量会引发名字遮盖现象,通过"NewbornBaby.hoursOfSleep"只能访问到NewbornBaby.hoursOfSleep而无法访问到NewParent.hoursOfSleep。名字规则由Java语言规范第三版第六章定义。
18 楼 sunlong 2010-07-03  
恩,俺的代码有问题……sh*t!哈哈,楼主修正后是正确滴~
17 楼 maozj 2010-07-03  
ckn126 写道
小弟运行出来的结果和案列之中出来的结果一样的,并不是楼主所说的结果,不知楼主是不是创建了子类的对象才会产生这样的结果,并且小弟使用的版本为
java version "1.6.0_20"
Java(TM) SE Runtime Environment (build 1.6.0_20-b02)
Java HotSpot(TM) Client VM (build 16.3-b01, mixed mode, sharing)

刚刚纠正了下 谢谢
16 楼 ckn126 2010-07-03  
小弟运行出来的结果和案列之中出来的结果一样的,并不是楼主所说的结果,不知楼主是不是创建了子类的对象才会产生这样的结果,并且小弟使用的版本为
java version "1.6.0_20"
Java(TM) SE Runtime Environment (build 1.6.0_20-b02)
Java HotSpot(TM) Client VM (build 16.3-b01, mixed mode, sharing)
15 楼 bugmenot 2010-07-03  
楼上的各位大大们在讨论的时候为何没有人把自己测试的代码以文本形式贴出来保证大家用同样的代码测试呢?
原始代码在官网可以找到,http://www.artima.com/insidejvm/ed2/lifetype4.html
// On CD-ROM in file classlife/ex2/NewParent.java
class NewParent {

    static int hoursOfSleep = (int) (Math.random() * 3.0);

    static {
        System.out.println("NewParent was initialized.");
    }
}

// On CD-ROM in file classlife/ex2/NewbornBaby.java
class NewbornBaby extends NewParent {

    static int hoursOfCrying = 6 + (int) (Math.random() * 2.0);

    static {
        System.out.println("NewbornBaby was initialized.");
    }
}

// On CD-ROM in file classlife/ex2/Example2.java
class Example2 {

    // Invoking main() is an active use of Example2
    public static void main(String[] args) {

        // Using hoursOfSleep is an active use of NewParent,
        // but a passive use of NewbornBaby
        int hours = NewbornBaby.hoursOfSleep;
        System.out.println(hours);
    }

    static {
        System.out.println("Example2 was initialized.");
    }
}


Example2的Java代码本身是个陷阱。代码里虽然写的是NewbornBaby.hoursOfSleep,但因为hoursOfSleep不是NewbornBaby而是NewParent的静态变量,程序实际访问也是通过NewParent访问的
public static void main(java.lang.String[]);
  Code:
   Stack=2, Locals=2, Args_size=1
   0:   getstatic       #11; //Field NewParent.hoursOfSleep:I
   3:   istore_1
   4:   getstatic       #8; //Field java/lang/System.out:Ljava/io/PrintStream;
   7:   iload_1
   8:   invokevirtual   #9; //Method java/io/PrintStream.println:(I)V
   11:  return


各位大大贴运行结果请贴上使用的源码和编译后main方法的字节码来比对。
14 楼 sunlong 2010-07-02  
真是奇怪了,竟然有人是,有人不是,看来谁的代码肯定有问题。
13 楼 sunlong 2010-07-02  
guzhan 写道
可能楼主把NewbornBaby中的hoursOfCrying敲成了hoursOfSleep

人家就是hoursOfSleep好吧……文章中也是哇
12 楼 guzhan 2010-07-02  
可能楼主把NewbornBaby中的hoursOfCrying敲成了hoursOfSleep
11 楼 gogole_09 2010-07-02  
maozj 写道
java version "1.6.0_17"
Java(TM) SE Runtime Environment (build 1.6.0_17-b04)
Java HotSpot(TM) Client VM (build 14.3-b01, mixed mode, sharing)

我比较感兴趣的是,为什么在上面的版本会出现问题? 期待楼主解答……
10 楼 maozj 2010-07-02  
java version "1.6.0_17"
Java(TM) SE Runtime Environment (build 1.6.0_17-b04)
Java HotSpot(TM) Client VM (build 14.3-b01, mixed mode, sharing)
9 楼 maozj 2010-07-02  
zhangkaitao 写道
maozj 写道
lydawen 写道
maozj 写道
zhangkaitao 写道
-------------------------
正确输出(大家都知道):
Example2 was initialized.
Newparent was initialized.
NewbornBaby was initialized.
7


这个肯定是你代码错了

--------------------------------------
你可以验证下


验证:翻开《深入JVM第二版》到第X章,肯定不会错.感觉这书要看个1遍,回头再看,理解消化,还有不错的

上述代码的执行正确与否 我的验证是在jdk1.6下。。。 当然,我也是说它针对当前jdk版本的验证。 你运行过这段代码?

我的JDK就行,
java version "1.6.0_10-rc2"
Java(TM) SE Runtime Environment (build 1.6.0_10-rc2-b32)

你在java version "1.6.0_17"下测测
8 楼 zhangkaitao 2010-07-02  
maozj 写道
lydawen 写道
maozj 写道
zhangkaitao 写道
-------------------------
正确输出(大家都知道):
Example2 was initialized.
Newparent was initialized.
NewbornBaby was initialized.
7


这个肯定是你代码错了

--------------------------------------
你可以验证下


验证:翻开《深入JVM第二版》到第X章,肯定不会错.感觉这书要看个1遍,回头再看,理解消化,还有不错的

上述代码的执行正确与否 我的验证是在jdk1.6下。。。 当然,我也是说它针对当前jdk版本的验证。 你运行过这段代码?

我的JDK就行,
java version "1.6.0_10-rc2"
Java(TM) SE Runtime Environment (build 1.6.0_10-rc2-b32)
7 楼 浪客剑心 2010-07-02  
我测试了一下,在jdk5下和原来一样,是正确的!
6 楼 sunlong 2010-07-02  
我今天正好也看到这个地方,我在1.6下面验证了一下,这儿的确现在不正确了。事实上也是这样的父类的静态变量初始化,然后是子类的静态变量。
5 楼 maozj 2010-07-02  
lydawen 写道
maozj 写道
zhangkaitao 写道
-------------------------
正确输出(大家都知道):
Example2 was initialized.
Newparent was initialized.
NewbornBaby was initialized.
7


这个肯定是你代码错了

--------------------------------------
你可以验证下


验证:翻开《深入JVM第二版》到第X章,肯定不会错.感觉这书要看个1遍,回头再看,理解消化,还有不错的

上述代码的执行正确与否 我的验证是在jdk1.6下。。。 当然,我也是说它针对当前jdk版本的验证。 你运行过这段代码?
4 楼 lydawen 2010-07-02  
maozj 写道
zhangkaitao 写道
-------------------------
正确输出(大家都知道):
Example2 was initialized.
Newparent was initialized.
NewbornBaby was initialized.
7


这个肯定是你代码错了

--------------------------------------
你可以验证下


验证:翻开《深入JVM第二版》到第X章,肯定不会错.感觉这书要看个1遍,回头再看,理解消化,还有不错的
3 楼 maozj 2010-07-02  
zhangkaitao 写道
-------------------------
正确输出(大家都知道):
Example2 was initialized.
Newparent was initialized.
NewbornBaby was initialized.
7


这个肯定是你代码错了

--------------------------------------
你可以验证下
2 楼 zhangkaitao 2010-07-02  
-------------------------
正确输出(大家都知道):
Example2 was initialized.
Newparent was initialized.
NewbornBaby was initialized.
7


这个肯定是你代码错了
1 楼 berlou 2010-07-02  
在这个领域,没有什么东西是永远如我党般永远正确的。
很多知识随着技术的进步,都变成了错误.

相关推荐

    类(型)的生命周期--装载、连接、初始化、卸载

    类(型)的生命周期--装载、连接、初始化、卸载 帮助你正确理解类的产生与消亡

    Java虚拟机类装载的原理及实现

    类装载不仅涉及将类文件中的字节码加载到内存中,还包含了校验、准备和初始化等多个步骤。本文旨在深入剖析JVM中的类装载系统,探讨类装载的原理、实现及其应用场景。 #### Java虚拟机的类装载实现与应用 ##### ...

    装载问题-回溯算法-java实现

    ### 装载问题与回溯算法 #### 一、装载问题概述 装载问题是一种经典的组合优化问题,在实际生产和生活中有着广泛的应用。该问题的基本形式是:给定一系列物品(如集装箱),每个物品都有一定的重量,现在有一个...

    Java深度历险(2)--深入类装载器

    3. **初始化**:执行类构造器`&lt;clinit&gt;`方法。 #### 类装载器的层次结构 Java的类装载器遵循一种层次结构,主要包括以下几种类型: 1. **Bootstrap ClassLoader**(启动类装载器):这是JVM自带的类装载器,用于...

    Java虚拟机类装载:原理、实现与应用.doc

    类装载过程不仅涉及基本的类查找和导入,还包含了链接、验证、准备、解析和初始化等多个阶段,这些步骤确保了Java程序的安全性和可靠性。 1. **装载过程**: - **装载**:这个阶段主要是寻找指定的类或接口的二...

    azxnet#thinking-in-java#6.9 初始化和类装载1

    装载的时候,所有static对象和static代码块都会按照本来的顺序初始化(亦即它们在类定义代码里写入的顺序)。保证这个顺序是非常关键的,因为衍生类的初始化可

    quanke#think-in-java#6.9 初始化和类装载1

    装载的时候,所有static对象和static代码块都会按照本来的顺序初始化(亦即它们在类定义代码里写入的顺序)。保证这个顺序是非常关键的,因为衍生类的初始化可

    Java类装载过程_.docx

    - 初始化类的子类(除非是接口) - 虚拟机启动时指定的启动类(main方法所在的类) 需要注意的是,除了以上六种主动用法,其他对类的被动用法不会触发初始化。例如,仅通过子类引用父类的静态字段不会导致父类的...

    深入JVM内核—原理、诊断与优化视频教程-6. 类装载器

    6. **类的生命周期**:类装载器不仅负责加载类,还参与类的初始化、使用和卸载过程。加载阶段包括找到.class文件并转换为字节码;验证阶段检查字节码是否符合Java规范;准备阶段分配静态变量内存并初始化为默认值;...

    2.装载机三维模型-2020.zip

    【装载机三维模型-2020.zip】这个压缩包包含了一个装载机的三维模型,主要针对的是工业设计和机械工程领域。模型是由SolidWorks(SW)软件创建的,这是一款广泛使用的三维CAD(计算机辅助设计)工具,专门用于产品...

    嵌入式系统初始化分析与UCOS-II移植

    ### 嵌入式系统初始化分析与UCOS-II移植 #### 一、嵌入式系统设计导论 在《嵌入式系统设计导论》这一章节中,主要讲解了基于32位微处理器与实时操作系统的相关知识。这部分内容不仅为初学者提供了深入理解嵌入式...

    jvm类装载器原理

    最后的初始化阶段,会执行类的静态初始化代码块和静态变量的初始化。 在Java中,ClassLoader是一个抽象类,位于`java.lang`包中,它是所有类装载器的基类。理解ClassLoader的关键在于掌握几个核心方法: 1. `load...

    Java虚拟机类装载机制

    链接是将装载的类与JVM环境连接起来,包括: - **校验**:确保类文件的字节码符合Java语言规范,避免运行时异常。 - **准备**:为类的静态变量分配内存,并初始化为默认值。 - **解析**:将符号引用转换为直接引用...

    Java虚拟机类装载:原理、实现与应用

    首先,类装载的过程分为三个主要阶段:装载、链接和初始化。装载阶段涉及寻找并导入类或接口的二进制数据,通常由类装载器(ClassLoader)执行。链接阶段则包括校验、准备和解析,校验确保二进制数据的正确性,准备...

    Java虚拟机类装载.doc

    resolve参数告诉方法是否需要解析类,在初始化类之前,应考虑类解析,并不是所有的类都需要解析,如果JVM只需要知道该类是否存在或找出该类的超类,那么就不需要解析。 * defineClass方法这个方法接受类文件的字节...

    JAVA虚拟机的类装载机制的原理分析与应用研究.pdf

    类装载机制是Java虚拟机在运行时动态加载和初始化类的过程。这一过程涉及到了四个主要角色:类装载器(ClassLoader)、类的二进制表示、验证(Verification)、准备(Preparation)以及初始化(Initialization)。...

    装载问题-分支限界算法-java实现

    1. 初始化FIFO队列和剪枝函数。 2. 生成可能的解决方案,并将其存储在FIFO队列中。 3. 使用剪枝函数来判断当前方案是否需要继续搜索。 4. 如果当前方案需要继续搜索,则将其存储在FIFO队列中,并继续搜索。 5. 重复...

    8051单片机的UART0串口初始化

    3、初始化程序(以后使用可直接调用此初始化函数)。SYSCLK与BAUDRATE参数修改即可 void UART0_Init (void) { SCON0 = 0x10; // SCON0: 8-bit variable bit rate // level of STOP bit is // 使能RX接收 //...

    ARM处理器系统初始化过程.docx

    本文将详细介绍ARM处理器系统初始化过程中涉及的重要步骤与关键技术点。 #### 二、初始化流程解析 ##### 1. 关闭MMU、中断及Cache - **禁止MMU**: 通过写入系统控制协处理器寄存器1的第0位来禁止内存管理单元(MMU...

    深入java虚拟机加载初始化

    这一过程对于Java应用程序而言至关重要,因为它涉及到如何正确地读取、解析以及初始化类文件。 #### Java加载初始化的关键概念 Java程序在运行过程中涉及几个关键的概念,包括类加载、连接以及初始化等阶段。 1. ...

Global site tag (gtag.js) - Google Analytics