如果对执行顺序不是很理解的童鞋,建议先看我的第一篇文章
在上一篇《java中在创建对象时候的初始化顺序》中大致的介绍了在继承,多态等情况下,对象大致的初始化顺序。这节讲讲一些特殊的情况,特别是和构造器结合起来,在构造器中调用一些方法的时候,出现的现象。我们先看例子(内容出自《think in java》300-301页)。
A类--父类
package extend;
public class A {
public A(){
draw();
}
public void draw(){
System.out.println("调用了父类的draw方法");
}
}
B类--子类
package extend;
public class B extends A{
public int i = 1;
public B(int i){
this.i=i;
}
public void draw(){
System.out.println("调用的子类的方法");
System.out.println("i 等于:"+i);
}
public static void main(String[] args) {
B b = new B(5);
}
}
结果:
i 等于:0
调用的子类的方法
怎么样!结果有些让你失望和疑惑吧,第一个疑惑为什么调用B中的draw方法,第二个为什么i=0。我看到这时,我迷糊了好久,但是后来想了想又觉得合理。
理由呢?还是从初始化顺序说起,我们知道子类对象的创建,一定会调用父类的构造器(不一定是无参的)这是在一般构造器中没有调用其他方法的时候,如果父类构造器调用了其他的方法,也就是"绑定"(如果对绑定不熟悉或是不清楚可以看我的另外一个文章《final讲解》)了其他方法的时候会出现什么问题呢,大家看到了结果,发现调用了子类的方法。为什么会这样呢???
问题的根源是绑定,到底绑定的哪个方法,A中draw还是B中draw,这个是由创建的对象决定的,也就是说你创建的是B对象,那么是由B对象决定的,但是有人会说,你这个例子A中的draw方法被覆盖,可以说是B对象决定的,但是如果A中有其他的方法,而B没有覆盖,那么肯定会调用A中的方法,怎么说是B决定的呢?这种说法也没错,但是我的也没错,为什么?因为B继承了A,那么B继承了A的所有的可以继承的方法,所以这个方法也可以认为是B的。
第一个疑惑解决了,第二个呢?为什么i为0,不是B中已经初始化了么,不是说属性在构造器之前就初始化了么?这个要说说初始化另外一个问题,我们知道属性不给它赋值也不会报错,不是0,null,就是false嘛,对,确实是这样的,这样一个初始化的过程是在一切事物之前就完成的,也就是说,在什么都没有发生前面,这些属性就赋予默认值了。下一步按照上篇文章讲到的,调用基类的构造器了,基类构造器中的draw方法是B中的方法,而B此时i还是0,所以结果就是那样。
讲到这里,相信大家明白了。 总结几句话,第一句:在多态的情况下,创建的对象决定了调用的方法。第二句:给对象赋予默认值会在其他任何情况发生前。第三句:不要有事没事在构造器中绑定其他方法。
分享到:
相关推荐
在Java编程语言中,程序初始化的顺序是一个关键概念,它涉及到类加载、对象创建以及执行流程的安排。了解这些顺序对于编写高效、无错误的...在实际项目中,合理利用初始化顺序可以帮助我们优化资源加载,提高程序性能。
在实际开发中,理解这个初始化顺序是非常重要的,尤其是在设计复杂的类结构或者涉及单例模式、线程安全初始化等场景时。如果在构造器或初始化块中依赖其他静态或非静态成员,必须确保这些成员在需要之前已经被正确...
在Java编程语言中,类继承是面向对象设计的一个核心特性,它允许我们创建一个新类(子类)作为现有类(父类)的扩展。当我们谈论“Java类继承初始化顺序”时,涉及到的关键知识点包括构造器、成员变量的初始化、...
在Java中,类的初始化顺序遵循一定的规则: 1. **静态成员变量的初始化**:当类被加载到JVM中时,静态成员变量首先被初始化。 2. **静态初始化块的执行**:紧随静态成员变量之后,静态初始化块被执行。 3. **父类...
让我们深入探讨Java中的初始化顺序及其背后的机制。 1. **类加载阶段**: 在Java程序运行时,JVM会先加载类的字节码文件(.class文件)。这个过程包括加载、验证、准备、解析和初始化五个步骤。这里我们主要关注...
在 Java 中,实例变量的初始化顺序是按照定义的顺序进行的,而静态变量的初始化顺序则是按照定义的顺序,并且只在第一次访问时初始化。 在上面的示例代码中,我们可以看到,类变量和实例变量的初始化顺序是按照定义...
总之,理解并有效地使用静态和对象初始化块是Java开发中的关键技能,它们可以帮助我们更好地控制类和对象的初始化过程,确保代码的高效性和正确性。在实际编程中,我们应该根据需求谨慎选择合适的初始化策略,以优化...
在面向对象语言中(如Java、C#等),当创建一个继承自某个基类的子类对象时,会有一个特定的初始化顺序。这个顺序通常遵循以下步骤: 1. **基类静态成员初始化**:如果基类中有任何静态成员,则会在程序启动时按照...
Java对象的初始化顺序是一个关键的编程概念,它涉及到类加载、静态初始化、实例初始化等多个步骤。下面我们将详细探讨这些步骤。 首先,当程序运行并创建一个新的对象时,JVM(Java虚拟机)会按照特定的顺序来初始...
同时,掌握类变量初始化顺序可以避免因误解而导致的错误,特别是在多线程环境中,对静态变量的并发访问和初始化顺序的控制需要特别注意。 总之,深入理解Java的ClassLoader机制和类变量初始化顺序是提升Java编程...
在Java编程语言中,对象初始化是一个关键的概念,它涉及到类加载、对象实例化以及成员变量的赋值。本文将深入探讨Java中对象初始化的顺序,帮助开发者理解这一过程的细节。 首先,Java类的加载过程分为三个阶段:...
在 Java 编程语言中,类的初始化顺序对于理解程序的行为至关重要。特别是当涉及到静态域(静态变量)、非静态域(实例变量)、静态块、非静态块以及构造函数时,明确它们的初始化顺序有助于避免潜在的编程错误。 ...
在Java中,类的初始化顺序是一个经常被问及的面试题目,尤其对于Java程序员和工程师来说,了解这个知识点是必须的。在Java中,类的初始化顺序是面试中的经典问题之一,它涉及到继承、静态成员以及实例成员等多个方面...
普通初始化块在创建对象时会被隐式调用,并且在执行构造器之前运行。这意味着,如果你在类中有多个初始化块,它们将按照它们在代码中的顺序依次执行。初始化块可以用于设置对象的初始状态,特别是当某些初始化逻辑...
Java中的对象初始化流程是编程实践中一个非常重要的概念,它涉及到类加载、静态初始化块、实例初始化块、构造器等多个方面。下面将详细解释这个过程。 首先,对象初始化流程的起点是程序的入口点,即`main`方法。当...
在 Java 中,静态变量的初始化顺序是按照它们在类中的定义顺序进行的。如果一个静态变量依赖于另一个静态变量的值,那么这两个变量的初始化顺序是重要的。 在给定的代码中,我们可以看到有多个静态变量的声明和初始...
在 Java 中,类的元素初始化顺序遵循以下规则: 1. **静态变量与静态初始化块**: 首先,Java 解释器会执行类中的静态变量初始化和静态初始化块。这些静态元素的初始化只会在类加载时执行一次,并且按照它们在源...
子类 --构造器 这个输出揭示了在继承关系中类的初始化顺序: 1. **静态成员和静态初始化块**:首先,会按照父类到子类的顺序初始化静态变量和执行静态初始化块。在上面的例子中,"父类 --静态变量" 和 "子类 --静态...
Java 变量初始化的时机是指在 Java 语言中变量的初始化过程,包括变量的声明、初始化和赋值的步骤。 Java 变量声明 在 Java 语言中,每个变量必须先声明,然后才能使用。声明变量时必须指定该变量的数据类型。...