4.6 一文带你搞懂对象初始化


0.前言

  • 在之前的文章中学习了编写简单的构造器,可以定义对象的初始状态。
  • Java 提供了多种编写构造器的机制。下面将详细地介绍这些机制。

1.重载

  • 如果多个方法(比如, StringBuilder 构造器方法)有相同的名字、不同的参数,便产生了重载

例如, 可以如下构造一个空的 StringBuilder 对象:
StringBuilder messages = new StringBuilder();
或者, 可以指定一个初始字符串:
StringBuilder todoList = new StringBuilder("To do:\n");

重载解析:

  • 编译器必须挑选出具体执行哪个方法,它通过用 各个方法给出的参数类型与特定方法调用所使用的值类型进行匹配来挑选出相应的方法。
    如 果编译器找不到匹配的参数, 就会产生编译时错误,因为根本不存在匹配, 或者没有一个比其他的更好。(这个过程被称为重载解析(overloading resolution)。

注:

Java 允许重载任何方法, 而不只是构造器方法。
因此,要完整地描述一个方法, 需要指出方法名以及参数类型。这叫做方法的签名(signature)

例如, String 类有 4 个 称为 indexOf 的公有方法。它们的签名是

indexOf(int) 
indexOf(int, int) 
indexOf(String)
indexOf(String,int)
  • 返回类型不是方法签名的一部分。也就是说, 不能有两个名字相同、 参数类型也相 同却返回不同类型值的方法。
    如下就是错误的:

在这里插入图片描述

2.默认域初始化

  • 如果在构造器中没有显式地给域赋予初值,那么就会被自动地赋为默认值数值为 0、 布尔值为 false、 对象引用为null
  • 仔细看一下 Employee类。假定没有在构造器中对某些域进行初始化, 就会默认 地将 salary 域初始化为 0, 将 name 和 hireDay 域初始化为 null。

3.无参数的构造器

  • 很多类都包含一个无参数的构造函数,对象由无参数构造函数创建时, 其状态会设置为 适当的默认值。
  • 如果在编写一个类时没有编写构造器, 那么系统就会提供一个无参数构造器。这个构造 器将所有的实例域设置为默认值。于是, 实例域中的数值型数据设置为 0、 布尔型数据设置 为 false、 所有对象变量将设置为 null
    在这里插入图片描述
  • 如果类中提供了至少一个构造器, 但是没有提供无参数的构造器, 则在构造对象时如果 没有提供参数就会被视为不合法
    在这里插入图片描述

4.显式域初始化

  • 可以在类定义中, 直接将一个值赋给任何域,比如我上面那张图的private double d=10.3d;
  • 在执行构造器之前,先执行赋值操作。当一个类的所有构造器都希望把相同的值赋予某 个特定的实例域时,这种方式特别有用。

Employee类,其中每个雇员有一个 id 域。可以使用下列方式进行初始化:
在这里插入图片描述

5.参数变量名

  • 可以将参数变量名用同样的名字将实例域屏蔽起来

例如,如果将参数命名为 salary, salary将引用这个参数, 而不是实例域。 但是,可以采用 this, salary 的形式访问实例域。this指示隐式参数,也就是当前所构造的对象。

public Employee(String naie, double salary) { 
this.name = name; 
this,salary = salary; 
} 

6. this调用另一个构造器

  • 关键字 this 引用方法的隐式参数,即引用调用这个方法的对象。然而,这个关键字还有另外一个含义。
    如果构造器的第一个语句形如 this(...), 这个构造器将调用同一个类的另一个构造器
    在这里插入图片描述
  • 当调用 new Employee(100) 时, Employee(double) 构造器将调用 Employee(String,double) 构造器。

7.初始化块

前面已经讲过两种初始化数据域的方法:

  • 在构造器中设置值
  • 在声明中赋值

实际上,Java 还有第三种机制, 称为初始化块(initializationblock)。在一个类的声明中, 可以包含多个代码块。只要构造类的对象,这些块就会被执行。例如:

在这里插入图片描述

  • 在这个示例中,无论是否使用构造器构造对象,name域都在对象初始化块中被初始化。首先运行初始化块,然后才运行构造器的主体部分。 这种机制不是必需的,也不常见。通常会直接将初始化代码放在构造器中。

由于初始化数据域有多种途径,所以列出构造过程的所有路径可能相当混乱。下面是调 用构造器的具体处理步骤:

  • 1 ) 所有数据域被初始化为设置的值,不设置则为默认值(0、false 或 null)。
  • 2 ) 按照在类声明中出现的次序, 依执行所有域初始化语句和初始化块
  • 3 ) 如果构造器第一行调用了第二个构造器,则执行第二个构造器主体 ) 执行这个构造器的主体.
    在这里插入图片描述
  • 如果对类的静态域进行初始化的代码比较复杂,那么可以使用静态的初始化块。 将代码放在一个块中,并标记关键字 static。
  • 在类第一次加载的时候, 将会首先执行静态static域进行初始化,然后执行普通初始化块,最后执行构造器函数。
    在这里插入图片描述

8. 对象析构与 finalize 方法

  • 有些面向对象的程序设计语言,特别是 C++, 有显式的析构器方法,其中放置一些当对 象不再使用时需要执行的清理代码。在析构器中, 最常见的操作是回收分配给对象的存储空间。由于 Java 有自动的垃圾回收器,不需要人工回收内存, 所以 Java 不支持析构器。
  • 当然,某些对象使用了内存之外的其他资源, 例如,文件或使用了系统资源的另一个对 象的句柄。在这种情况下,当资源不再需要时, 将其回收和再利用将显得十分重要。
  • 可以为任何一个类添加 finalize 方法。finalize 方法将在垃圾回收器清除对象之前调用。 在实际应用中,不要依赖于使用 finalize 方法回收任何短缺的资源, 这是因为很难知道这个方法什么时候才能够调用。
  • 如果某个资源需要在使用完毕后立刻被关闭, 那么就需要由人工来管理。对象用完时, 可以应用一个 close方法来完成相应的清理操作

参考:《java核心技术卷Ⅰ》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章