`
javasons
  • 浏览: 7312 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

基础知识(1、类的初始化顺序)

阅读更多
转贴 来源于网址:http://zangweiren.iteye.com

大家在去参加面试的时候,经常会遇到这样的考题:给你两个类的代码,它们之间是继承的关系,每个类里只有构造器方法和一些变量,构造器里可能还有一段代码对变量值进行了某种运算,另外还有一些将变量值输出到控制台的代码,然后让我们判断输出的结果。这实际上是在考查我们对于继承情况下类的初始化顺序的了解。

我们大家都知道,对于静态变量、静态初始化块、变量、初始化块、构造器,它们的初始化顺序依次是(静态变量、静态初始化块)>(变量、初始化块)>构造器。我们也可以通过下面的测试代码来验证这一点:
Java代码
public class InitialOrderTest {  
 
    // 静态变量  
    public static String staticField = "静态变量";  
    // 变量  
    public String field = "变量";  
 
    // 静态初始化块  
    static {  
        System.out.println(staticField);  
        System.out.println("静态初始化块");  
    }  
 
    // 初始化块  
    {  
        System.out.println(field);  
        System.out.println("初始化块");  
    }  
 
    // 构造器  
    public InitialOrderTest() {  
        System.out.println("构造器");  
    }  
 
    public static void main(String[] args) {  
        new InitialOrderTest();  
    }  


public class InitialOrderTest {

// 静态变量
public static String staticField = "静态变量";
// 变量
public String field = "变量";

// 静态初始化块
static {
System.out.println(staticField);
System.out.println("静态初始化块");
}

// 初始化块
{
System.out.println(field);
System.out.println("初始化块");
}

// 构造器
public InitialOrderTest() {
System.out.println("构造器");
}

public static void main(String[] args) {
new InitialOrderTest();
}
}

运行以上代码,我们会得到如下的输出结果:

静态变量
静态初始化块
变量
初始化块
构造器

这与上文中说的完全符合。那么对于继承情况下又会怎样呢?我们仍然以一段测试代码来获取最终结果:
Java代码
class Parent {  
    // 静态变量  
    public static String p_StaticField = "父类--静态变量";  
    // 变量  
    public String p_Field = "父类--变量";  
 
    // 静态初始化块  
    static {  
        System.out.println(p_StaticField);  
        System.out.println("父类--静态初始化块");  
    }  
 
    // 初始化块  
    {  
        System.out.println(p_Field);  
        System.out.println("父类--初始化块");  
    }  
 
    // 构造器  
    public Parent() {  
        System.out.println("父类--构造器");  
    }  
}  
 
public class SubClass extends Parent {  
    // 静态变量  
    public static String s_StaticField = "子类--静态变量";  
    // 变量  
    public String s_Field = "子类--变量";  
    // 静态初始化块  
    static {  
        System.out.println(s_StaticField);  
        System.out.println("子类--静态初始化块");  
    }  
    // 初始化块  
    {  
        System.out.println(s_Field);  
        System.out.println("子类--初始化块");  
    }  
 
    // 构造器  
    public SubClass() {  
        System.out.println("子类--构造器");  
    }  
 
    // 程序入口  
    public static void main(String[] args) {  
        new SubClass();  
    }  


class Parent {
// 静态变量
public static String p_StaticField = "父类--静态变量";
// 变量
public String p_Field = "父类--变量";

// 静态初始化块
static {
System.out.println(p_StaticField);
System.out.println("父类--静态初始化块");
}

// 初始化块
{
System.out.println(p_Field);
System.out.println("父类--初始化块");
}

// 构造器
public Parent() {
System.out.println("父类--构造器");
}
}

public class SubClass extends Parent {
// 静态变量
public static String s_StaticField = "子类--静态变量";
// 变量
public String s_Field = "子类--变量";
// 静态初始化块
static {
System.out.println(s_StaticField);
System.out.println("子类--静态初始化块");
}
// 初始化块
{
System.out.println(s_Field);
System.out.println("子类--初始化块");
}

// 构造器
public SubClass() {
System.out.println("子类--构造器");
}

// 程序入口
public static void main(String[] args) {
new SubClass();
}
}

运行一下上面的代码,结果马上呈现在我们的眼前:

父类--静态变量
父类--静态初始化块
子类--静态变量
子类--静态初始化块
父类--变量
父类--初始化块
父类--构造器
子类--变量
子类--初始化块
子类--构造器

现在,结果已经不言自明了。大家可能会注意到一点,那就是,并不是父类完全初始化完毕后才进行子类的初始化,实际上子类的静态变量和静态初始化块的初始化是在父类的变量、初始化块和构造器初始化之前就完成了。

那么对于静态变量和静态初始化块之间、变量和初始化块之间的先后顺序又是怎样呢?是否静态变量总是先于静态初始化块,变量总是先于初始化块就被初始化了呢?实际上这取决于它们在类中出现的先后顺序。我们以静态变量和静态初始化块为例来进行说明。

同样,我们还是写一个类来进行测试:
Java代码
public class TestOrder {  
    // 静态变量  
    public static TestA a = new TestA();  
      
    // 静态初始化块  
    static {  
        System.out.println("静态初始化块");  
    }  
      
    // 静态变量  
    public static TestB b = new TestB();  
 
    public static void main(String[] args) {  
        new TestOrder();  
    }  
}  
 
class TestA {  
    public TestA() {  
        System.out.println("Test--A");  
    }  
}  
 
class TestB {  
    public TestB() {  
        System.out.println("Test--B");  
    }  


public class TestOrder {
// 静态变量
public static TestA a = new TestA();

// 静态初始化块
static {
System.out.println("静态初始化块");
}

// 静态变量
public static TestB b = new TestB();

public static void main(String[] args) {
new TestOrder();
}
}

class TestA {
public TestA() {
System.out.println("Test--A");
}
}

class TestB {
public TestB() {
System.out.println("Test--B");
}
}

运行上面的代码,会得到如下的结果:

Test--A
静态初始化块
Test--B

大家可以随意改变变量a、变量b以及静态初始化块的前后位置,就会发现输出结果随着它们在类中出现的前后顺序而改变,这就说明静态变量和静态初始化块是依照他们在类中的定义顺序进行初始化的。同样,变量和初始化块也遵循这个规律。

了解了继承情况下类的初始化顺序之后,如何判断最终输出结果就迎刃而解了。
分享到:
评论

相关推荐

    java中类的初始化顺序

    1. **单个类的初始化顺序** ```java public class InitialOrderTest { // 静态成员变量 public static String staticField = "静态"; // 静态初始化块 static { System.out.println(staticField); System....

    JAVA面试题解惑系列(一)——类的初始化顺序-JAVA程序员JAVA工程师面试必看.pdf

    总结来说,对于Java程序员和工程师而言,了解类的初始化顺序不仅是面试中常问的问题,也是日常编程中必须掌握的基础知识。这一知识的掌握,能够帮助开发者更好地管理内存、避免初始化时的错误和数据竞争等问题,从而...

    “礼让”原则学习Java对象初始化顺序.pdf

    "Java 对象初始化顺序学习指南" 在学习 Java 编程语言时,对象初始化顺序是一个非常重要的知识点,但是许多学生却感到困惑和困难。事实上,Java 对象初始化顺序并不难理解,只需要掌握“礼让”原则和 JVM 的执行...

    SD卡的SPI模式的初始化顺序

    1. SD卡的官方资料:了解SD卡的官方资料是非常重要的,虽然官方资料的内容可能不太友好,但对基础知识的了解是必要的。SD协议不需要看,因为它只是一个基础协议。 2. 清晰明了的MMC卡时序图:了解MMC卡的时序图可以...

    Flex Application 初始化顺序

    提供的ff_bookmarks.html文件可能是保存的书签或浏览历史,它与Flex Application初始化顺序的知识点关联性较小,可能属于开发者个人的学习记录或资源收藏。不过,在实际项目中,类似这样的资源可以用来快速找回重要...

    tft初始化程序.rar_4.5"TFT初始化_9481_ILI9338、_TFT初始化指令_tft初始化

    在"tft初始化程序"中,通常包含一系列的初始化脚本或代码,这些代码会按照特定顺序执行上述步骤。对于9481和ILI9338,由于它们的寄存器配置有所不同,所以需要使用特定的初始化指令集。这些指令通常以十六进制格式给...

    顺序线性表的初始化、插入与输出

    ### 数据结构:顺序线性表的初始化、插入与输出(C/C++) #### 知识点解析 在计算机科学中,数据结构是组织和存储数据的一种特定方式,它允许高效地进行数据访问和修改。顺序线性表是一种基本的数据结构,它通过一...

    Java类加载器:静态变量初始化.docx

    在本文中,我们讨论了 Java 类加载器中的静态变量初始化机制,了解了静态变量的初始化顺序和类加载器的生命周期。通过对静态变量初始化机制的理解,我们可以更好地掌握 Java 语言的基础知识,并更好地应用 Java 语言...

    Java中对象初始化顺序的详细介绍

    这种情况下,初始化顺序如下:首先,`Lower`类的实例创建并分配默认值,然后调用`Upper`的构造器,接着执行`Initializer.initialize()`,该方法根据对象的实际类型(`Lower`)来设置字段的值。 5. **默认值**:即使...

    Java变量初始化

    Java 变量初始化是 Java 语言的基础知识点之一,但也往往被学习者所忽略。 Java 变量初始化的时机是指在 Java 语言中变量的初始化过程,包括变量的声明、初始化和赋值的步骤。 Java 变量声明 在 Java 语言中,每个...

    顺序表的初始化及基本操作.pdf

    1. 初始化顺序表,设置存储空间大小和初始长度等属性。 2. 定位元素,在顺序表中查找特定元素的序号。 3. 插入元素,在指定位置添加一个新元素。 4. 删除元素,移除顺序表中的特定元素。 文件内容中还展示了一系列...

    PIC18系列单片机各个功能模块的通用初始化代码

    1. **PIC18系列微控制器架构**:了解其内部结构,如CPU、寄存器、定时器/计数器、中断系统等,是编写初始化代码的基础。 2. **串行通信(SCI)**:包括UART(通用异步接收/发送器)的配置,如波特率设定、奇偶校验、...

    Java——对象初始化顺序使用详解

    tr); fatherStr = "fatherStr...总之,Java对象初始化顺序是编程过程中必须掌握的基础知识,它涉及到类的加载、实例化过程以及字段和方法的调用顺序。正确理解和运用这些知识,能够使我们写出更加健壮、高效的代码。

    数据初始化设置,及代码

    下面我们将对数据初始化的重要性和相关的知识点进行详细的介绍。 一、软件可移植性 软件可移植性是衡量软件在不同平台、操作系统和硬件环境下的运行能力。它是软件开发中的一项重要指标。提高软件的可移植性,可以...

    内核初始化

    ### 内核初始化知识点详解 #### 一、内核初始化概述 **内核初始化**是操作系统启动过程中的关键环节之一,主要涉及系统硬件资源的初始化、内核数据结构的建立、核心服务的启动等步骤。良好的初始化过程可以确保...

    顺序表上的基本操作实现

    根据给定文件的信息,本文将详细介绍顺序表的基本操作实现,包括初始化、创建、插入、删除、查找、遍历、逆置、以及合并等操作。同时也会对比顺序表与链表的特点,帮助读者更好地理解这两种数据结构的应用场景。 ##...

    JAVA面试题解惑系列

    #### 类初始化顺序的基础知识 在Java中,类的初始化遵循一定的顺序,主要包括静态变量、静态初始化块、实例变量、初始化块以及构造器。这些部分的初始化顺序可以概括为: 1. **静态变量和静态初始化块**:首先被...

    Windows深入剖析(初始化篇)下

    1. 内核初始化:内核加载后,会执行初始化过程,包括硬件设备的初始化、内存管理的设置、中断处理机制的建立等。此时,内核会调用HAL(Hardware Abstraction Layer)层,使操作系统能与不同的硬件平台交互。 2. VMM...

    顺序表的操作

    例如,在给定代码中,`initLinklist`函数用于初始化顺序表: ```c int initLinklist(LinkList *l) { *l = (LinkList)malloc(sizeof(Node)); (*l)->next = NULL; return OK; } ``` 这里通过动态分配内存并设置...

Global site tag (gtag.js) - Google Analytics