作者:臧圩人
网址:http://zangweiren.javaeye.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();
}
}
运行以上代码,我们会得到如下的输出结果:
静态变量
静态初始化块
变量
初始化块
构造器
这与上文中说的完全符合。那么对于继承情况下又会怎样呢?我们仍然以一段测试代码来获取最终结果:
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");
}
}
运行上面的代码,会得到如下的结果:
Test--A
静态初始化块
Test--B
大家可以随意改变变量a、变量b以及静态初始化块的前后位置,就会发现输出结果随着它们在类中出现的前后顺序而改变,这就说明静态变量和静态初始化块是依照他们在类中的定义顺序进行初始化的。同样,变量和初始化块也遵循这个规律。
了解了继承情况下类的初始化顺序之后,如何判断最终输出结果就迎刃而解了。
分享到:
相关推荐
System.out.println("父类--静态初始化块"); } // 初始化块 { System.out.println(p_Field); System.out.println("父类--初始化块"); } // 构造器 public Parent() { System.out.println(...
这个顺序表明,无论类之间的继承关系如何,初始化顺序始终是:静态变量和静态初始化块先于非静态成员。在创建对象时,父类的初始化先于子类。这是Java语言规范所规定的,确保在子类访问父类的静态或非静态成员时,...
- 静态初始化块(static{}):如果类中存在静态初始化块,该块的代码会在类加载后的准备阶段执行,用于初始化静态变量或执行其他静态设置任务。 - 静态变量的赋值:接着,静态变量会被赋予它们的初始值,这可以是...
总之,Java类继承初始化顺序涉及到静态和非静态初始化块、构造器的调用以及方法的覆盖。理解这些概念对于编写健壮的、易于维护的Java代码至关重要。在实际编程中,应合理利用继承特性,同时注意避免不必要的复杂性和...
这里类变量初始化的时机为两处,而没有在构造器中这一说。这也很容易理解,因为类变量是类加载的时候执行的初始化,且只执行一次,而调用构造器是对象实例化执行的,每实例化一次对象,执行一次。 总结 Java 变量...
首先,需要了解Java类初始化的基本规则,即在类的静态变量、静态初始化块、变量、初始化块、构造器这五个部分中,它们的初始化顺序依次是:静态变量、静态初始化块、变量、初始化块、构造器。这个顺序在单个类中是...
需要注意的是,静态初始化块只在类被加载时执行一次,而实例初始化块(构造函数)则会在每次创建类的实例时执行。静态变量的初始化是在类加载时完成的,而实例变量的初始化则在对象创建时进行。 在实际开发中,对...
总之,Java代码的初始化顺序是类加载的必然过程,涉及到静态和实例初始化块、构造函数、成员变量初始化以及继承关系的影响。这个demo是学习和理解这些概念的重要工具,通过实际操作可以加深对Java内存管理和对象生命...
Java 中的初始化顺序是按照定义的顺序进行的,而静态变量的初始化顺序则是按照定义的顺序,并且只在第一次访问时初始化。 Java 初始化顺序的知识点总结: * 类变量(静态变量)和实例变量(对象变量)的区别 * ...
1. **静态成员和静态初始化块**:首先,会按照父类到子类的顺序初始化静态变量和执行静态初始化块。在上面的例子中,"父类 --静态变量" 和 "子类 --静态变量" 先被初始化,然后分别执行对应的静态初始化块。 2. **...
静态初始化块主要用于初始化类级别的变量,即静态变量。由于它是在类加载时执行,所以它总是在任何对象创建之前运行。静态初始化块不能访问非静态成员,包括实例属性和实例方法,因为它们依赖于对象实例,而静态初始...
在 JAVA 中,类的初始化顺序可以分为四个阶段:静态变量、静态初始化块、变量、初始化块和构造器。其中,静态变量和静态初始化块的初始化顺序是最高的,接着是变量和初始化块,最后是构造器。 在了解类的初始化顺序...
Java中的静态变量(static变量)是在类加载时初始化的,而不是在对象创建时。静态变量属于类,而不属于任何特定的对象,因此它们是共享的,所有类实例都可以访问。了解静态变量的初始化顺序对于理解和避免潜在的编程...
3. **父类的非静态部分**:在创建子类实例时,首先执行父类的非静态变量初始化和非静态初始化块,然后调用父类的构造器。 4. **子类的非静态部分**:最后执行子类的非静态变量初始化和非静态初始化块,以及子类的...
静态块是Java类中用于初始化静态变量的代码块。它们在类加载时执行,且只执行一次。无论创建多少个类的实例,静态块只会被执行一次。这是因为在Java中,类的静态成员是与类相关的,而非类的实例。 ```java public ...
在Java编程语言中,构造器(Constructor)是一个特殊的方法,主要负责对象的初始化工作。当创建一个新的类实例时,构造器会被自动调用。构造器的名称必须与类名完全相同,且没有返回类型,包括void。理解并熟练运用...
在 `Table` 类和 `Cupboard` 类的构造器中,可以看到静态变量的初始化会导致它们关联的实例方法 `f()` 被调用。例如,`Table` 类的构造器在创建静态变量 `b2` 时调用了 `b2.f(1)`,这将打印出 "f(1)"。同样,`...
2. 静态初始化块:当类第一次被加载时执行,按块的顺序执行。 3. 实例字段:在构造器内部,按照声明的顺序初始化。 4. 实例初始化块:在构造器执行之前,按块的顺序执行。 例如: ```java public class MyClass { ...
1. **静态变量和静态初始化块**:首先,按照声明的顺序,执行父类的静态变量和静态初始化块,然后执行子类的静态变量和静态初始化块。这是因为静态成员属于类,不依赖于类的实例,所以在创建任何对象之前就已经完成...