`

65.对象的构造以及初始化

 
阅读更多

有关类的继承的内容大概其就这么多了。之前提过了对象的构造以及初始化。现在在类的继承的基础上,继续来说对象的构造以及初始化,主要讨论子类如何完成继承父类的初始化。

 

当调用类的构造器来创建对象时,它将给新建的对象分配内存,并对对象进行初始化操作。

 

现在我们来探讨对对象进行初始化操作时候的细节。

 

 

 

对象的初始化操作将递归如下的步骤来进行:

 

 


1.设置实例变量的值为缺省的初始值 (0, false, null),不同的数据类型有不同的初始值。


2.调用类的构造器 (但是还没有执行构造方法体),绑定构造器参数。


3.如果构造器中有this()调用,则根据this()调用的参数调用相应的重载构造器,然后,转到步骤5;否则转到步骤4。


4.除java.lang.Object类外,调用父类的中的初始化块初始化父类的属性,然后调用父类构造器,如果在构造器中有super()调用,则根据super()中的参数调用父类中相应的构造器。

5.使用初始化程序和初始化块初始化成员。

6.执行构造器方法体中其他语句。

所谓的初始化块,就是我们前面提到的所谓“游离块”。不管使用哪个构造器创建对象,它都会被首先运行,然后才是构造器的主体部分被执行。


我们来看一个例子:

 

class Person {
 private String name;

 private int age;

 private String sex;

 public Person() {
  System.out.println("构造器Person()被调用");
  sex = "Male";
  System.out.println("name=" + name + " ,age=" + age + " ,sex=" + sex);
 }

 public Person(String theName) {
  // 调用构造器Person()
  this();
  System.out.println("构造器Person(String theName)被调用");
  name = theName;
  System.out.println("name=" + name + " ,age=" + age + " ,sex=" + sex);
 }

 public Person(String theName, int theAge) {
  // 调用构造器Person(String theName)
  this(theName);
  System.out.println("构造器Person(String theName,int theAge)被调用");
  age = theAge;
  System.out.println("name=" + name + " ,age=" + age + " ,sex=" + sex);
 }

 // 初始化块
 {
  name = "Tony Blair";
  age = 50;
  sex = "Female";
  System.out.println("初始化块执行后:name=" + name + " ,age="
+ age + " ,sex=" + sex);
 }
}

public class TestPerson {
 public static void main(String[] args) {
  Person person = new Person();
 }
}


编译执行上面的程序,将会得到如下的输出:
初始化块执行后:name=Tony Blair ,age=50 ,sex=Female
构造器Person()被调用
name=Tony Blair ,age=50 ,sex=Male


可以看到,初始化块会先于构造器调用执行。读者可以将main()方法中调用的创建Person对象的构造器换成其他两个,在观察它的结果。同样可以得出上面的结论。

提示:初始化块的机制并不是必须的,你完全可以将属性的初始化和属性的声明结合在一起,如:    String name =  "Tony Blair";
下面我们看一个对象初始化的例子,以加深对对象初始化的理解。

class Person {
 private String name;

 private int age;

 private String sex;

 public Person() {
  System.out.println("构造器Person()被调用");
  sex = "Male";
  System.out.println("name=" + name + " ,age=" + age + " ,sex=" + sex);
 }

 public Person(String theName) {
  System.out.println("构造器Person(String theName)被调用");
  name = theName;
  System.out.println("name=" + name + " ,age=" + age + " ,sex=" + sex);
 }

 public Person(String theName, int theAge) {
  System.out.println("构造器Person(String theName,int theAge)被调用");
  name = theName;
  age = theAge;
  System.out.println("name=" + name + " ,age=" + age + " ,sex=" + sex);
 }

 // 初始化块
 {
  name = "Tony Blair";
  age = 50;
  sex = "Female";
  System.out.println("Person初始化块执行后:name=" + name + " ,age="
+ age + " ,sex=" + sex);
 }
}


这里定义了一个父类Person,它里面定义了三个构造器以及一个初始化块。


我们再来定义一个Person类的子类Teacher,如下:

class Teacher extends Person {
 // 部门
 String department;

 // 教龄
 int schoolAge;

 public Teacher() {
  System.out.println("构造器Teacher()被调用");
 }

 public Teacher(String name) {
  // 调用父类中的构造器Person(String theName)
  super(name);
  System.out.println("构造器Teacher(String name)被调用");
 }

 public Teacher(int theSchoolAge) {
  schoolAge = theSchoolAge;
 }

 public Teacher(String dept, int theSchoolAge) {
  // 调用本类中重载的构造器Teacher(int theSchoolAge)
  this(theSchoolAge);
  department = dept;
 }

 // 初始化块
 {
  department = "教务部";
  System.out.println("Teacher初始化块执行后:name=" + name + " ,age=" + age
    + " ,sex=" + sex);
 }
}


这个类中定义了四个构造器:一个不带参数的构造器;一个带一个String数据类型参数的构造器,它通过super()显式调用父类的构造器;一个带一个int数据类型参数的构造器;一个带两个参数的构造器,通过this()来调用类中带int类型参数的构造器。


public class TestInit {
 public static void main(String[] args) {
  System.out.println("------------------------------------");
  Teacher t1 = new Teacher();
  System.out.println("");

  System.out.println("------------------------------------");
  Teacher t2 = new Teacher("Tom");
  System.out.println("");

  System.out.println("------------------------------------");
  Teacher t3 = new Teacher("财务部", 20);
 }
}


这个程序通过三种构造器来创建三个Teacher对象,因为调用的构造器不同,所以对象初始化的步骤也有所不同。因为在这几个程序中,在几个关键部分都已经有信息打印到控制台,所以,只要执行这个程序,就可以看出各个调用构造器创建对象的运行细节。


编译并运行TestInit,可以在控制台上得到如下的信息:
------------------------------------
Person初始化块执行后:name=Tony Blair ,age=50 ,sex=Female
构造器Person()被调用
name=Tony Blair ,age=50 ,sex=Male
Teacher初始化块执行后:name=Tony Blair ,age=50 ,sex=Male
构造器Teacher()被调用

------------------------------------
Person初始化块执行后:name=Tony Blair ,age=50 ,sex=Female
构造器Person(String theName)被调用
name=Tom ,age=50 ,sex=Female
Teacher初始化块执行后:name=Tom ,age=50 ,sex=Female
构造器Teacher(String name)被调用

------------------------------------
Person初始化块执行后:name=Tony Blair ,age=50 ,sex=Female
构造器Person()被调用
name=Tony Blair ,age=50 ,sex=Male
Teacher初始化块执行后:name=Tony Blair ,age=50 ,sex=Male

 

 

分享到:
评论
4 楼 谁说我不是会员 2016-10-30  
liuwei1981 写道
hupu_2014 写道
根据你的执行结果,父类属性你应该是定义为public


测试过就知道了,代码和运行结果是匹配的,这是利用了java构造器执行顺序原因。



测试过没通过,访问不到呀
3 楼 liuwei1981 2014-08-28  
hupu_2014 写道
根据你的执行结果,父类属性你应该是定义为public


测试过就知道了,代码和运行结果是匹配的,这是利用了java构造器执行顺序原因。
2 楼 hupu_2014 2014-08-22  
根据你的执行结果,父类属性你应该是定义为public
1 楼 xierfly 2014-04-16  
  department = "教务部";
  System.out.println("Teacher初始化块执行后:name=" + name + " ,age=" + age
    + " ,sex=" + sex);

我想问,这句怎么执行的呢?

Teacher初始化块执行后:name=Tony Blair ,age=50 ,sex=Male


父类的属性是private,子类怎么调用到的?

相关推荐

    C++构造函数初始化列表

    构造函数初始化列表是C++中一个非常重要的特性,它允许程序员在对象创建时直接对类中的成员进行初始化,而不是先分配内存再赋值,这在效率和安全性上都有显著优势。 #### 构造函数初始化列表的作用与语法 构造函数...

    VS2005入门视频教程-018.利用构造函数初始化对象.rar

    本系列教程的课程安排参考了多本.net 1.1以及在目前的2.0新书的基础上认真编订。不敢夸口本系列多了不起,但至少敢保证你看完本系列,再做完每个小结的测试,你入门是绝对没有问题的!做一个简单的网站是绝对可以的!祝愿...

    天轰穿系列教程之-16利用构造函数初始化对象

    天轰穿系列教程之-16利用构造函数初始化对象天轰穿系列教程之-16利用构造函数初始化对象天轰穿系列教程之-16利用构造函数初始化对象天轰穿系列教程之-16利用构造函数初始化对象天轰穿系列教程之-16利用构造函数初始...

    对象初始化流程梳理对象初始化流程梳理

    Java中的对象初始化流程是编程实践中一个非常重要的概念,它涉及到类加载、静态初始化块、实例初始化块、构造器等多个方面。下面将详细解释这个过程。 首先,对象初始化流程的起点是程序的入口点,即`main`方法。当...

    WPF 对象初始化器_1 对象初始化器_1

    ### WPF 对象初始化器详解 #### 一、对象初始化器概述 对象初始化器是C# 3.0引入的一项新特性,它简化了对象创建的过程。在传统的面向对象编程中,创建对象后通常需要手动设置各个属性。这种方式不仅繁琐,而且...

    SpringBoot项目启动时实现调用一次初始化方法.docx

    1. 对象初始化——构造方法 2. 对象初始化——`@PostConstruct`注解的方法 3. 对象初始化——实现了`InitializingBean`接口的`afterPropertiesSet`方法 4. 对象初始化——自定义的`init`方法 5. ---容器启动完毕后.....

    c++ 子类构造函数初始化及父类构造初始化的使用

    "C++ 子类构造函数初始化及父类构造初始化的使用" C++ 中的构造函数初始化是指在类对象创建时对其进行初始化的过程。构造函数是类的特殊成员函数,用于初始化类对象。在 C++ 中,子类构造函数的初始化涉及到父类...

    C++对象初始化[文].pdf

    在C++中,对象初始化的方法多种多样,包括直接初始化、复制初始化以及针对内置类型和类类型的特定方式。 对于内置类型,C++提供了三种初始化方式: 1. **空初始化**:不提供初始值,例如`int i;`或`new int;`。在...

    java中对象创建、初始化、引用

    - **初始化对象**:通过构造器初始化新创建的对象,设置其初始状态。 - **赋值**:最后,将创建好的对象的引用赋给之前声明的引用变量。 例如,下面的代码展示了如何创建一个`A`类的对象: ```java A a1 = new A()...

    Java静态初始化块和对象初始化块

    这是因为在每个构造函数开始时,都会隐式地调用对象初始化块。 **比较与结合** 静态初始化块和对象初始化块的执行顺序不同。静态初始化块在类加载时执行,而对象初始化块在创建新对象时执行。它们可以相互配合,以...

    编程思想14章构造函数的初始化表达式

    在C++编程中,构造函数是一种特殊的成员函数,它的主要任务是初始化类的对象。构造函数的初始化表达式是创建对象时执行的关键步骤,用于设置新对象的状态。在第14章“构造函数的初始化表达式”中,我们将深入探讨这...

    程序设计中基于构造函数的对象初始化方法研究.zip_C++_suddenh4l

    在C++编程语言中,对象初始化是一个至关重要的过程,它涉及到类的实例化以及成员变量的赋初值。本文将深入探讨基于构造函数的对象初始化方法,以帮助开发者更好地理解和运用这一核心概念。 构造函数是C++中一种特殊...

    C++关于构造函数的初始化

    本文将深入探讨C++构造函数中的初始化,包括传统的赋值方式、括号赋值、冒号初始化(也称为成员初始化列表)以及函数体初始化。 首先,C++中存在两种初始化方式:赋值运算符赋值和括号赋值。例如: ```cpp int a =...

    java程序初始化顺序

    在Java编程语言中,程序初始化的顺序是一个关键概念,它涉及到类加载、对象创建以及执行流程的安排。了解这些顺序对于编写高效、无错误的代码至关重要。以下是对Java程序初始化顺序的详细说明: 1. **类加载阶段**...

    类和对象的初始化过程.zip

    总结,这个压缩包文件提供了关于Java中类和对象初始化的实例,包括静态和非静态成员的处理、继承、构造函数的调用顺序等。通过分析并运行这些代码,开发者可以更深入地理解Java的初始化机制。对于初学者来说,这是一...

    C++\测试 对象成员构造函数、基类构造函数、派生类本身的构造函数 的先后顺序.rar

    总结来说,C++对象构造的顺序是: 1. 按照声明顺序初始化成员对象的构造函数。 2. 调用基类的构造函数(如果有的话)。 3. 执行派生类构造函数的主体部分,初始化派生类特有的成员。 这个顺序保证了对象的构造过程...

    计数器实现了默认构造函数用于初始化,c++面向对象程序设计书上的习题

    在C++中,构造函数是一种特殊类型的成员函数,它在创建对象时自动调用,用于初始化对象的状态。默认构造函数是指没有参数的构造函数,它的作用是当创建对象时,如果没有提供任何初始值,就使用默认值来设置对象的...

    java中类的初始化顺序

    类的初始化涉及到多个方面,包括静态成员变量、实例成员变量、静态初始化块、实例初始化块以及构造函数等。本文将详细探讨Java中类的初始化过程及其顺序,并通过具体的代码示例来帮助理解这一过程。 #### 二、基础...

    初始化和清理.ppt初始化和清理.ppt初始化和清理.ppt初始化和清理.ppt

    本节主要讨论了Java中的构造器、成员初始化、对象创建过程、垃圾回收以及垃圾回收器的工作原理。 4.1 构造器 构造器是Java中用于初始化新创建对象的特殊方法。它的名字与类名完全相同,没有返回类型,且不能声明为...

Global site tag (gtag.js) - Google Analytics