java初始化构造函数调用顺序
类初始化时构造函数调用顺序:
(1)初始化对象的存储空间为零或null值;
(2)调用父类构造函数;
(3)按顺序分别调用类成员变量和实例成员变量的初始化表达式;
(4)调用本身构造函数。
例子:
public class Dollar extends Money{
Rmb r=new Rmb()
public Dollar(){
System.out.println("Dollar is construct!");
}
public static void main(String[] args){
new Dollar();
}
}
class Money{
public Money(){
System.out.println("Money is construct");
}
}
class Rmb{
public Rmb(){
System.out.println("RMB is construct");
}
}
输出结果:
Money is construct
RMB is construct
Dollar is construct!
我们再自己写一个程序,以测试运行顺序:



输出结果:

说明此时的运行顺序为:
- 父类类成员变量
- 父类静态块
- 自身类成员变量
- 自身静态块
- 父类实例成员变量
- 父类块
- 父类构造器
- 自身实例成员变量
- 自身块
- 自身构造器
再来看下伯乐在线小组的一个热门讨论帖:
携程 Java 工程师的一道面向对象面试题
public class Base {
private String baseName = "base";
public Base() {
callName();
}
public void callName() {
System.out.println(baseName);
}
static class Sub extends Base {
private String baseName = "sub";
public void callName() {
System.out.println(baseName);
}
}
public static void main(String[] args) {
Base b = new Sub();
}
}
求这段程序的输出。
来自未老莫还乡 的评论:
【不要在构造器里调用可能被重载的虚方法,这是极度危险的】。构造器的初始化顺序大概是 父类静态块 子类静态块 父类初始化语句 父类构造函器 子类初始化语句 子类构造器。父类构造器执行的时候,调用了子类的重载方法,然而子类的类字段还在刚初始化的阶段,刚完成内存布局,只能输出null。
来自ihuning 的精华评论:
看我大师归来:
1. Base b = new Sub();
2. Base b = 直接忽略,从 new Sub();开始
3. 类加载器加载 Base,Sub 类到jvm;
4. 为Base,Sub 类中的两个属性baseName 分配存储空间,但是不初始化;
注意:属性的初始化时放在构造器中,按照代码顺序执行的。
5. new Sub会调用Sub的无参构造器,而在这个构造器中会隐式调用父类Base的无参构造器;
6. 父类Base的构造器中代码本质是
public Base()
{
baseName = "base";
callName();
}
即父类的属性baseName 的值为base。但为何输出null,骚年别急。
7. 因为父类构造器方法是在子类中调用的,即大环境是子类。此时,调用的方法callName()当然是指子类的方法。而这个方法打印的属性baseName当然也是子类的。那现在子类的属性baseName的值是多少呢?答案是null.因为此时子类Sub的构造器内代码本质是:
super();
baseName="sub";
此时baseName="sub"还没执行。
因此,最后的值当然是null.
附上代码:
public class A {
static B b = new B(3);
B bb = new B(4); A() {
System.out.println("A constructor");
} static {
System.out.println("A static block");
}
{
System.out.println("A block");
}
}public class C extends A {
static B b = new B(1);
B bb = new B(2);
C() {
System.out.println("C constructor");
}
static {
System.out.println("C static block");
}
{
System.out.println("C block");
}
public static void main(String[] args) {
C c = new C();
}
}
class B {
B(int i) {
System.out.println("B"+i);
}
}
java初始化构造函数调用顺序的更多相关文章
- C# 构造函数调用顺序
了解C#的一个类的加载过程,对于语言机制的理解和写出高效的语言很有帮助,这里简单介绍一下类的实例的构造函数调用过程.C#类的实例的构造过程是,先为实例的数据字段分配内存,并对所有字段按字节置零(0或者 ...
- JAVA & .NET创建对象构造函数调用顺序
JAVA 定义Person类 package models; public class Person { public Person() { System.out.println("pe ...
- java初始化块执行顺序
java中初始化块的执行顺序在构造器之前,多个初始化块之间定义在前的先执行.如下: public class InitialBlockTest { // The first one { System. ...
- C++派生类构造函数调用顺序(详解)
我们来看下面一段代码: class B1 { public: B1(int i) {cout<<"constructing B1 "<<i<<e ...
- java abstract构造函数调用
构造函数是对象的基本,没有构造函数就没有对象.如果在父类中(这里就是你的抽象类)中显示的写了有参数的构造函数,在子类继承是就必须写一个构造函数来调用父类的构造函数 public abstract cl ...
- java 初始化顺序
java 变量类型如下: 实例变量: 类变量: 初始化途经如下: 实例变量 --声明时,初始化: --非静态初始化块内,初始化: --构造函数内,初始化: 实例1: public class bean ...
- Java初始化顺序
package com.helei.init; class Log { public static String fatherStaticString(){System.out.println(&qu ...
- Java 初始化字段方式和顺序
Java 初始化字段方式和顺序: 类加载时直接初始化静态字段; 类加载时调用静态方法初始化静态字段; 实例化对象时,在调用构造函数之前代码块中初始化字段; 实例化对象时,在调用构造函数之时初始化字段; ...
- C++ 全局构造函数调用的顺序
C++的全局类和静态类的构造函数是在main函数之前调用的.但是,不同的类的构造函数以什么顺序调用呢? 对于g++编译器来说,这个顺序是由链接时,文件顺序决定的. 我们用一个例子来说明这一点. 我们有 ...
随机推荐
- Openvswitch原理与代码分析(6):用户态流表flow table的操作
当内核无法查找到流表项的时候,则会通过upcall来调用用户态ovs-vswtichd中的flow table. 会调用ofproto-dpif-upcall.c中的udpif_upcall_hand ...
- sqlite3基础
要使用sqlite,首先需要添加库文件libsqlite3.dylib.当你搜索libsqlite3关键字时,会发现还有一个libsqlite3.0.dylib的库文件,这里还是建议添加libsqli ...
- android EditText inputType说明
在开发的过程中,通常会用到EditText,如何让虚拟键盘来适应输入框中内容的类型,通常我们都会在xml文件中加入android:inputType="". android:inp ...
- python 字符串连接
字符串连接 方法1: 用字符串的join方法 a = ['a','b','c','d']content = ''content = ''.join(a)print content 方法2: 用字符串的 ...
- Android动画效果translate、scale、alpha、rotate详解
动画类型 Android的animation由四种类型组成 XML中 alpha 渐变透明度动画效果 scale 渐变尺寸伸缩动画效果 translate 画面转换位置移动动画效果 rotate 画面 ...
- Debian 基本设置
在此做一下记录,省得以后再老是去搜索了 我的debian版本v:8.1.0 我是在Hyper-V中装的,启动后一直ping不通网址,后来才知道Debian不能直接ping域名,只能ping IP... ...
- Android View的加载过程
大家都知道Android中加载view是从Activity的onCreate方法调用setContentView开始的,那么View的具体加载过程又是怎么的呢?这一节我们做一下分析. 首先追踪一下代码 ...
- SQL SERVER 使用select和union插入多条数据
insert into A(A) select '2' union select '3' union select '100' go select * from A
- 比较几种工具Python(x,y) Anaconda WinPython
浏览了一些相关的论坛,将几大工具的特点分别总结下: Python(x,y) 更新很慢,稳定性一般,默认带有很多包. WinPython 只能在windows上跑,界面友好,和Python(x,y)是 ...
- Metatable和Metamethod
Metatable和Metamethod是用来干啥的?它们可以使得表a和b的表达式“a + b”变得有意义,其中metatable使两个不相关的表a和b之间可以进行操作,而操作的具体行为比如说&quo ...