例1:
abstract class Glyph {
2 Glyph() {
3 System.out.println( " Glyph() before draw() " );
4 draw(); // 不明白的地方是这里.
5 System.out.println( " Glyph() after draw() " );
6 }
7 abstract void draw();
8 }
9
10 class RoundGlyph extends Glyph {
11 private int radius = 1 ;
12 RoundGlyph( int r) {
13 radius = r;
14 System.out.println( " RoundGlyph.RoundGlyph(), radius = " + radius);
15 }
16
17 void draw() {
18 // radius = z;
19 System.out.println( " RoundGlyph.draw(), radius = " + radius);
20 }
21 }
22
23 public class PolyConstructors {
24 public static void main(String[] args) {
25 new RoundGlyph( 5 );
26 }
27 }
答案:
1 Glyph() before draw()
2 RoundGlyph.draw(), radius = 0
3 Glyph() after draw()
4 RoundGlyph.RoundGlyph(), radius = 5
分析:分析
1类初始化时构造函数调用顺序:
2 首先加载类,遇到extends字样会停止加载当前类,加载父类,之后再继续加载。
3 当把一个类完全加载后,这个类的静态成员将被先加载。之后进行如下流程:
4(1)初始化对象的存储空间为零或null值;
5(2)调用父类构造函数;
6(3)按顺序分别调用类成员变量和实例成员变量的初始化表达式;
7(4)调用本身构造函数
8
9构造函数的初始化顺序:
101 .当执行new RoundGlyph( 5 )时,首先会加载‘RoundGlyph. class ’,但是这个时候JVM发现 RoundGlyph extends (继承于) Glyph ,所以他会加载Glyph. class
112 .然后会初始化Glyph类的static成员数据,这个类没有static成员数据,所以没有这一步。
123 .会执行Glyph类的构造函数Glyph()
134 .接着初始化RoundGlyph类的成员数据,最后调用RoundGlyph()构造函数来生产对象
例2:
1public class Test2 extends Test1 {
2 {
3 System.out.print( " 1 " );
4 }
5 Test2() {
6 System.out.print( " 2 " );
7 }
8 static {
9 System.out.print( " 3 " );
10 }
11 {
12 System.out.print( " 4 " );
13 }
14 public static void main(String[] args) {
15 new Test2();
16 }
17}
18
19class Test1 {
20 Test1() {
21 System.out.print( " 5 " );
22 }
23 static {
24 System.out.print( " 6 " );
25 }
26}
答案:635142
解析: 1( 1 ) 虚拟机试图加载Test2,其父类为Test1
2 ( 2 ) 虚拟机加载Test1
3 ( 3 ) Test1静态初始化 -----> 输出 " 6 "
4 ( 4 ) 虚拟机加载Test2
5 ( 3 ) Test2静态初始化 -----> 输出 " 3 "
6 ( 5 ) new Test2()构造Test2首先构造父类Test1
7 ( 6 ) Test1构造 -----> 输出 " 5 "
8 ( 7 ) Test2执行初始化语句块(虚拟机调用Test2初始化方法init) -----> 输出 " 1 " 和 " 4 "
9 ( 8 ) Test2构造 -----> 输出 " 2 "
10
11 =================================
12 先输出6:
13 因为父类的Static的变量 / 常量会被子类共享
14 所以,首先输出6
15 接着,会先初始化自身的static的变量 / 常量
16
17 然后,在构造函数中,会首先调用父类的默认构造函数(如果没有显示调用super(args)的话)
18 在调用父类构造函数时,在执行构造函数体中的数据内容时,先执行方法外的程序段,如变量申明,或者程序段。然后再调用构造函数中的程序段。
19 然后再执行自身的构造函数,执行前,也如上述说:在执行本构造函数体中的数据内容时,先执行方法外的程序段,如变量申明,或者程序段。然后再调用构造函数中的程序段。
20
21 这就是一个对象的实例化过程。
分享到:
相关推荐
在探讨继承中子类与父类构造函数及静态块的执行顺序时,我们首先需要理解构造函数和静态块的基本概念及其在Java中的作用。构造函数主要用于初始化对象的状态,而静态块则是在类加载到内存中时执行的一段代码,通常...
在 Java 中,static 块和构造函数的执行顺序是非常重要的。通常情况下,static 块在类加载时执行,而构造函数在类实例化时执行。下面是一个简单的示例代码: ```java public class WebSerivceTest { private ...
如果在类的构造函数中调用了其他构造函数,可以使用`this()`关键字,它会立即调用同一类中的另一个构造函数。 5. **构造函数与继承**:子类可以继承父类,并可以定义自己的构造函数。如果子类没有显式定义构造函数...
2. **构造函数调用顺序**:在子类构造函数中,必须先调用父类的构造函数(使用`super`),然后再执行子类构造函数中的其他代码。 3. **构造函数的可访问性**:子类只能访问具有相同或更宽松访问级别的父类构造函数。...
### Java 类中静态域、块,非静态域、块,构造函数的初始化顺序 #### 一、概述 在 Java 编程语言中,类的初始化顺序对于理解程序的行为至关重要。特别是当涉及到静态域(静态变量)、非静态域(实例变量)、静态块...
2. **继承关系中的构造函数执行顺序**:在创建子类对象时,会先执行父类的构造函数,然后再执行子类自己的构造函数。如果父类构造函数中有初始化其他类对象的操作,则会先执行这些对象的构造函数。 3. **构造函数与...
在Java编程语言中,了解静态代码块和构造方法的执行顺序是至关重要的,尤其是在处理类的初始化和对象的创建时。下面将详细解释这些概念及其执行逻辑。 首先,静态代码块(也称为静态初始化器)是由`static`关键字...
值得注意的是,静态构造函数的执行时间早于任何实例构造函数,而且静态构造函数的执行顺序取决于静态成员的引用顺序,而不是代码中定义的顺序。 静态变量,又称为类变量,它们是属于类的,而非类的实例。这意味着...
问题:子类继承父类,构造函数及公共属性的执行顺序是怎样的? 示例代码 <SPAN xss=removed>public class A extends C { B b = new B(); static H h = new H(); static { ...
7. **执行顺序**:当有类继承关系时,基类的静态构造函数先于派生类的静态构造函数执行。 8. **不可显式调用**:由于静态构造函数由系统自动调用,我们无法在代码中显式地调用它,也无法控制它的执行时机。 9. **...
初始化块的执行顺序同样遵循它们在类体中出现的顺序。 #### 示例代码分析 为了更好地理解类继承初始化顺序的概念,下面通过一段示例代码来进行详细分析: ```java class Base { public Base() { System.out....
下面将深入讨论构造器的机理、执行顺序、作用及与其他概念的区别。 一、构造器的机理 构造器是一种特殊的方法,用于初始化对象的创建。它的名称与类名相同,并且没有返回类型。构造器的作用是创建一个类的实例,...
在C#编程语言中,构造函数和析构函数是两种非常关键的特殊方法,它们分别负责对象的初始化...在实际编程中,要根据具体情况选择合适的构造函数类型,合理组织构造函数的调用顺序,以及适时地使用析构函数进行资源清理。
Java中静态初始化块的执行顺序 Java是一种面向对象的编程语言,静态初始化块是Java中的一个重要概念。静态初始化块是Java类中的一种特殊的初始化块,它用于初始化类的静态变量和静态方法。在Java中,静态初始化块的...
(但对于C++中的class对象,如果不显式初始化,则无论是否是`static`类型都会自动调用默认构造函数。) **特点:** - **记忆性:** 在两次函数调用之间,局部静态变量能够记住上次函数调用结束时的值。 - **全局性...
1. **执行顺序**:静态初始化块在非静态初始化块之前执行。当类第一次被加载时,JVM会按照它们在源代码中的顺序执行静态初始化块。 2. **类加载机制**:Java类的加载是懒加载的,即只有在类被首次使用时,JVM才会...
Java允许构造函数的重载,这意味着在同一个类中可以定义多个构造函数,只要它们的参数列表不同即可。这样做可以为创建对象提供不同的方式,根据传入的参数类型或数量来选择合适的构造函数。例如: ```java class ...
这说明在初始化一个对象时,总是会先执行基类的构造函数,然后再执行子类的构造函数。 对于虚方法调用,C# 编译器会进行一些额外的“动作”。例如,找出所调用对象的实际类型,以访问正确的方法表。例如: class ...
- 静态成员在类加载时初始化,因此如果静态成员依赖于运行时信息(如构造函数),可能导致错误。 - 尽量避免过多使用静态,因为它可能导致代码难以测试和维护,也可能造成全局状态,影响程序并发性能。 了解并...
创建此类对象时,构造函数的调用顺序是这样的:首先调用自身类的构造函数,但在构造函数体执行之前,会先调用成员对象的构造函数,按照成员对象在类定义中的顺序逐个初始化。析构函数的调用顺序则与构造函数相反,先...