其实java对象初始化顺序算是一个比较基础的java知识点。但是网上的文章多半描述不清,使用上一不小心就容易出问题。
所以在本文中,我想结合JLS和自己的理解,举例剖析问题的所在。
OK,我们先来看个模仿Dzone作者原意的简单例子:
package com.kenwublog.tmp;
public class A extends B {
public int a = 100;
public A() {
super();
System.out.println(a);
a = 200;
}
public static void main(String[] args) {
System.out.println(new A().a);
}
}
class B {
public B() {
System.out.println(((A) this).a);
}
}
例子代码很简单,不多做解释了,直接看输出:
0
100
200
对照这个输出,我们来详细分析一下对象的初始化顺序:
1,为A类分配内存空间,初始化所有成员变量为默认值,包括primitive类型(int=0,boolean=false,…)和Reference类型。
2,调用A类构造函数。
3,调用B类构造函数。
4,调用Object空构造函数。(java编译器会默认加此构造函数,且object构造函数是个空函数,所以立即返回)
5,初始化B类成员变量,因为B类没有成员变量,跳过。
6,执行sysout输出子类A的成员变量小a。// 此时为0
7,初始化A类成员变量,将A类成员变量小a赋值100。
8,执行sysout输出当前A类的成员变量小a。// 此时为100
9,赋值当前A类的成员变量小a为200。
10,main函数中执行sysout,输出A类实例的成员变量小a。// 此时为200
加粗的那两行描述是重点,结论是成员变量初始化是在父类构造函数调用完后,在此之前,成员变量的值均是默认值。
Dzone作者就是栽在这里,没有仔细分析成员变量初始化在对象初始化中的顺序,造成了程序未按原意执行。
其实这类问题,熟悉原理是一方面,本质上只要不在构造函数中插入过多的业务逻辑,出问题的概率也会低很多。
最后,我们再来看看JLS中给出的Java类对象初始化顺序定义,这是一个带条件分支的流程描述:
Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.
If this constructor begins with an explicit constructor invocation of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.
This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.
Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5. (In some early implementations, the compiler incorrectly omitted the code to initialize a field if the field initializer expression was a constant expression whose value was equal to the default initialization value for its type.)
Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally
分享到:
相关推荐
java面试题-类的初始化顺序.doc 大家在去参加面试的时候,经常会遇到这样的考题:给你两个类的代码,它们之间是继承的关系,每个类里只有构造器方法和一些变量,构造器里可能还有一段代码对变量值进行了某种运算,...
类继承的初始化顺序类继承的初始化顺序类继承的初始化顺序类继承的初始化顺序
类的初始化顺序,适用于任何一种面向对象的语言。真正了解面向对象的程序的流程。配有实例
本篇文章主要介绍了Spring 中如何控制2个bean中的初始化顺序,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
详细讲解java类中静态变量,普通标量,对象、基本类型的初始化顺序。
在上面的示例代码中,我们可以看到,类变量和实例变量的初始化顺序是按照定义的顺序进行的。同时,我们还可以看到,静态变量的初始化顺序是按照定义的顺序,并且只在第一次访问时初始化。 在 Java 中,static ...
介绍一下java程序初始化的顺序,这会对您以后的开发所有帮助
所有代码块是从上往下顺序执行的,所以代码块里面使用到的变量如果在块下面初始化会有问题 执行构造方法中内容。 所以看见的空构造方法,只能说第三部没有需要执行的内容。 下面举例子 public class TestClass { ...
具体内容见博客
对java类初始化以及顺序,详解,由于转载仅供大家参考!
JAVA面试题解惑系列(一)——类的初始化顺序 JAVA 是一门面向对象的编程语言,类的初始化顺序是 JAVA 程序员和 JAVA 工程师面试中一个非常重要的知识点。本文将详细讲解类的初始化顺序,并提供了相关的测试代码,...
(1)初始化顺序表L (2)从标准输入(键盘)逐个数据输入a,b,c,d,e元素 ,建立顺序表 (3)输出顺序表L (4)输出顺序表L的长度 (5)判断顺序表L是否为空 (6)输出顺序表L的第3个元素 (7)输出元素a的位置...
SD卡的SPI模式的初始化顺序 SD卡的SPI模式的初始化顺序是指SD卡在SPI模式下的初始化过程,该过程对开发SD卡非常有帮助。下面是SD卡的SPI模式的初始化顺序的知识点总结: 1. SD卡的官方资料:了解SD卡的官方资料是...
java类中静态域、块,非静态域、块,构造函数的初始化顺序,通过本例子,能够清楚了解到java类的初始化顺序
JAVA类的初始化顺序文.pdf
java 静态_非静态 字段_方法_代码块 子类父类构造_初始化顺序! 三个class 让你清清楚楚 第一个class java代码如下: package initialOrder; class Parent { // 静态变量 public static String p_StaticField...
使用c++实现顺序表的基本操作: 1、顺序表的初始化 2、顺序表的长度 3、顺序表插入元素 4、删除顺序表元素 5、遍历顺序表 6、查找顺序表元素
详细介绍了Java的静态成员变量、静态数据块、非静态成员变量和非静态成员变量等初始化顺序
这是我获得的java的代码,这个主要关于成员的初始化顺序和多态性,这个代码主要用于学习和交流,希望大家喜欢。