重载

如果多个方法有相同的名字、不同的参数,便产生了重载。
Java 允许重载任何方法,而不只是构造器方法。因此,要完整地描述一个方法,需要指出方法名以及参数类型。这叫做方法的签名(signature)。
例如,String类有4个称为indexOf的公有方法。它们的签名是:

  1. indexOf(int)
  2. indexOf(int, int)
  3. indexOf(String)
  4. indexOf(String, int)

返回类型不是方法签名的一部分。也就是说,不能有两个名字相同、参数类型也相同却返回不同类型值的方法。

默认域初始化

如果在构造器中没有显式地给域赋予初值,那么就会被自动地赋为默认值:数值为 0、布尔值为 false、对象引用为 null。然而,只有缺少程序设计经验的人才会这样做。确实,如果不明确地对域进行初始化,就会影响程序代码的可读性。

与局部变量不同,局部变量不会自动的初始化,但是域可以。

无参数的构造器

当你在编写一个类时没有编写构造器,那么系统就会自动提供一个无参构造器,这个构造器将所有的实例域设置为默认值。就像这样:

  1. public Empolyee()
  2. {
  3. name = "";
  4. salary = 0;
  5. hireDay = LocalDate.now();
  6. }

如果类中提供了至少一个构造器,但是没有提供无参数的构造器,则在构造对象时如果没有提供参数就会被视为不合法。
当然,也可以自己编写无参构造器。如果希望所有域被赋予默认值,可以这样编写无参构造器:

  1. public ClassName()
  2. {
  3. }

显式域初始化

在定义类的时候,可以直接将一个值赋值给域。例如:

  1. class Employee
  2. {
  3. private String name = "";
  4. ...
  5. }

在构造一个实例时,运行的顺序为:先执行赋值操作,再在构造器中赋值。当一个类的所有构造器都希望把相同的值赋予某个特定的实例域时,这种方式特别有用。
初始值不一定是常量,也可以是静态方法:

  1. class Employee
  2. {
  3. private static int nextId;
  4. private int id = assignId();
  5. ...
  6. private static int assignId()
  7. {
  8. int r = nextId;
  9. nextId++;
  10. return r;
  11. }
  12. ...
  13. }

调用另一个构造器

关键字 this 表示类方法中的隐式参数。然而,这个关键字还有另一个含义。
如果构造器的第一个语句(必须是第一个语句)形如 this(…),这个构造器将调用同一个类的另一个构造器。下面是一个典型的例子:

  1. public Employee(double s) {
  2. this("Employee #" + nextId, s); // calls Employee(String, double)
  3. nextId++;
  4. }

当调用 new Employee(60000)时,Employee(double)构造器将调用 Employee(String,double)构造器。
采用这种方式使用 this 关键字非常有用,这样对公共的构造器代码部分只编写一次即可。

初始化块

你可以在构造器中设置值,也可以在声明中赋值。你还可以在初始化块中来初始化域:

  1. class Employee {
  2. private static int nextId;
  3. private int id;
  4. private String name;
  5. private double salary;
  6. // object initialization block
  7. {
  8. id = nextId;
  9. nextId++;
  10. }
  11. public Employee(String n, double s) {
  12. name = n;
  13. salary = s;
  14. }
  15. public Employee() {
  16. name = "";
  17. salary = 0;
  18. }
  19. ...
  20. }

在这个示例中,无论使用那个构造器,id 域都在对象初始化块中被初始化。初始化块运行在构造器的前面。
值得注意的是,初始化块与显式域初始化有先后关系,例如:

  1. class Employee {
  2. private static int nextId;
  3. // object initialization block
  4. {
  5. id = nextId;
  6. nextId++;
  7. }
  8. private int id = 5;
  9. private String name;
  10. private double salary;
  11. }

使用无参构造器创建一个 Employee 类时,id 域的值为 5
我们已经讲到了很多的初始化数据域的方法,这里来说调用一个构造器,数据域的运行顺序:

  1. 所以数据域被初始化为默认值(0、false、null)
  2. 按照在类声明中出现的次序,依次执行所有域初始化语句和初始化块。
  3. 如果构造器第一行调用了第二个构造器,则执行第二个构造器主体。
  4. 执行这个构造器的主体。

当然也有静态的初始化块:

  1. // static initialization block
  2. static
  3. {
  4. Random generator = new Random();
  5. nextId = generator.nextInt(10000);
  6. }

静态初始化块,仅仅会加载一次。也就是上述的结果不会随着你创建新的实例而改变。当然,他也和静态初始化语句一样按照顺序执行。

对象析构域 finalize 方法

析构器:与构造器相对,是用来结束对象的声明周期的。
可以为任何一个类添加 finalize 方法。finalize 方法将在垃圾回收器清除对象之前调用。在实际应用中,不要依赖于使用 finalize 方法回收任何短缺的资源,这是因为很难知道这个方法什么时候才能够调用。
如果某个资源需要在使用完毕后立刻被关闭,那么就需要由人工来管理。对象用完时,可以应用一个 close 方法来完成相应的清理操作。