`
huiqinbo
  • 浏览: 344415 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java类中静态域、块,非静态域、块,构造函数的初始化顺序(回钦波)

阅读更多

java类中静态域、块,非静态域、块,构造函数的初始化顺序2

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

我们大家都知道,对于静态变量、静态初始化块、变量、初始化块、构造器,它们的初始化顺序以此是(静态变量、静态初始化块)>(变量、初始化块)>构造器。我们也可以通过下面的测试代码来验证这一点:

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();       
    }       
}      


运行以上代码,我们会得到如下的输出结果:
静态变量
静态初始化块
变量
初始化块
构造器

这与上文中说的完全符合。那么对于继承情况下又会怎样呢?我们仍然以一段测试代码来获取最终结果:


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();       
    }       
}      
  


运行一下上面的代码,结果马上呈现在我们的眼前:
父类--静态变量
父类--静态初始化块
子类--静态变量
子类--静态初始化块
父类--变量
父类--初始化块
父类--构造器
子类--变量
子类--初始化块
子类--构造器

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

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

同样,我们还是写一个类来进行测试:


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以及静态初始化块的前后位置,就会发现输出结果随着它们在类中出现的前后顺序而改变,这就说明静态变量和静态初始化块是依照他们在类中的定义顺序进行初始化的。同样,变量和初始化块也遵循这个规律。

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

分享到:
评论
2 楼 wwytwen123 2016-08-16  

    [*]
1 楼 ashy1q 2012-04-07  
楼主最后那段代码重复了,写了两遍。

知识很详细,很基础,学习了。

相关推荐

    java类中静态域、块,非静态域、块,构造函数的初始化顺序

    ### Java 类中静态域、块,非静态域、块,构造函数的初始化顺序 #### 一、概述 在 Java 编程语言中,类的初始化顺序对于理解程序的行为至关重要。特别是当涉及到静态域(静态变量)、非静态域(实例变量)、静态块...

    【Java】80例及结果

    从提供的【部分内容】中,我们可以提炼出Java语言中面向对象编程的几个核心概念,包括类的继承、构造函数的执行顺序、静态属性的初始化顺序、以及变量的作用域等方面的知识点。以下是详细解释: 1. 类的继承与构造...

    静态代码块

    在Java编程语言中,代码块是一种用于对对象或类进行初始化的有效手段。根据它们的作用域和执行时机的不同,代码块可以分为几种类型,其中最常见的两种是静态代码块(static code block)和构造代码块(instance ...

    JAVA函数使用手册

    12. **构造函数**:特殊类型的函数,用于初始化新对象。类可以有多个构造函数,根据参数列表进行重载。 13. **函数式编程**:Java 8引入了对函数式编程的支持,如Stream API,使得处理集合数据变得更加简洁和高效。...

    Java基础知识面试题系列一.docx

    3. **Java程序初始化顺序**:初始化顺序遵循以下原则: - 首先初始化静态变量和静态代码块,按定义顺序执行。 - 其次是父类的非静态部分,包括非静态变量和非静态代码块,再是父类构造函数。 - 最后是子类的非...

    java代码块测试

    3. **静态初始化块**:当类被加载到JVM(Java虚拟机)时,这些代码块被执行。它们用于初始化类级别的变量,不依赖于类的实例。 4. **finally代码块**:用于异常处理,无论是否抛出异常,finally块中的代码总会被...

    java 函数速查CHM

    6. **构造函数**:特殊类型的函数,用于对象的初始化。类名与构造函数相同,没有返回类型。 7. **匿名函数**:Java 8引入了Lambda表达式,允许创建没有名字的函数,常用于函数式接口。 8. **递归**:函数调用自身...

    java代码-日常练习33,代码块### 静态代码块 static{代码内容;} 随着类的加载就执行一次 构造器代码块 {代码内容;} 每创建对象就执行一次 局部代码块 {代码内容;} 方法执行一次执行一次

    在Java编程语言中,代码块是程序中一组按顺序执行的语句,它们可以有特定的作用域和执行时机。在日常练习33中,我们关注的是三种不同类型的代码块:静态代码块、构造器代码块和局部代码块。下面将详细讲解这三种代码...

    《Java 语言程序设计》阶段测试题

    在Java中,一个类的构造函数用于初始化该类的对象,并且在创建对象时自动调用。然而,如果构造函数中使用了与类中的变量同名的局部变量,则构造函数内部的变量将隐藏类中的变量。因此,在试题2中,尽管构造函数中...

    Java课件1

    默认构造函数没有参数,而自定义构造函数可以带有参数以进行初始化。例如,`Circle`类可以定义不同的构造函数,以处理不同半径的圆。 9.3 构造函数: 构造函数没有返回类型,名称与类名相同,主要用于对象初始化。...

    Java语言编码规范.pdf

    - 变量初始化的最佳时机和顺序,例如局部变量应在声明时初始化,而成员变量可以在声明时或构造函数中初始化。 - 对象的创建和初始化,包括构造函数的使用规则,以及如何使用静态代码块和实例代码块进行复杂的初始化...

    java1-6章测试题目.pdf

    26. **创建对象的内部过程**:分配内存、调用构造函数初始化、返回对象引用。 27. **值传递与引用传递**:Java中,对象作为参数传递实际上是引用传递,但不能改变对象本身,只能修改对象的内容。 28. **常用类、包...

    《JAVA语言程序设计》期末考试试题及答案2(应考必备题库)

    7. **静态初始化器**:静态初始化器(静态块)在类加载时执行,用于初始化静态成员。 8. **对象赋值**:Java中对象赋值实际上是创建了一个新对象的引用,并非复制整个对象。赋值操作不会生成属性相同的“新对象”。...

    java学习笔记

    5. **构造函数**:构造函数是类的一个特殊方法,用于初始化新创建的对象。默认情况下,如果程序员没有定义构造函数,JVM会提供一个无参构造函数,不做任何操作。但一旦程序员自定义了构造函数,JVM就不会再生成默认...

    分析JAVA程序设计期末考试试题.pdf

    静态初始化器(静态块)在类被加载到内存时由系统自动调用执行,用于类级别的初始化任务。在Java中,对象可以通过赋值操作符(等号)传递引用,但这并不意味着创建了新对象,实际上是两个引用指向同一个对象,而不是...

    2014年Java最全面试题以及答案.

    final类中的方法默认是final的,而final类中的成员变量则必须在声明时或构造器中初始化。 10. 继承时候类的执行顺序问题,一般都是选择题,问你将会打印出什么? 在继承体系中,如果有一个方法在父类和子类中都有实现...

    1_java-选择题不带答案.doc

    6. 构造函数:Java 中,构造函数用于初始化类的新实例。A 错误,因为类可以没有显式定义的构造函数,Java 会提供一个默认的无参构造函数。B 错误,构造函数没有返回类型。C 错误,构造函数可以带参数。D 正确,类...

    java期末考试知识点总结.doc

    4. **初始化顺序**:先初始化基类的属性,然后是派生类自己的属性。 5. **构造方法的重载**:构造函数可以被重载,即在一个类中可以有多个构造函数,但它们的参数列表不同。 #### 七、类的修饰符 1. **Public类**...

    Java面试题以及答案整理.pdf

    初始化顺序为:静态初始化块 -> 构造器 -> 实例初始化块。 12. **内部类的实现方式** 内部类分为:成员内部类、局部内部类、匿名内部类和静态内部类。 13. **Java实现排序和序列化** 可以使用Java内置的`...

    C++经典面试题库 附带参考答案.docx

    25. 初始化成员顺序:成员初始化顺序由声明顺序决定,与初始化列表中顺序无关。 26. 类与对象关系:类是对象的蓝图,对象是类的具体实例。 27. 访问属性:public(公开)、protected(保护)、private(私有)。 ...

Global site tag (gtag.js) - Google Analytics