重载
如果多个方法有相同的名字、不同的参数,便产生了重载。
Java 允许重载任何方法,而不只是构造器方法。因此,要完整地描述一个方法,需要指出方法名以及参数类型。这叫做方法的签名(signature)。
例如,String类有4个称为indexOf的公有方法。它们的签名是:
indexOf(int)
indexOf(int, int)
indexOf(String)
indexOf(String, int)
返回类型不是方法签名的一部分。也就是说,不能有两个名字相同、参数类型也相同却返回不同类型值的方法。
默认域初始化
如果在构造器中没有显式地给域赋予初值,那么就会被自动地赋为默认值:数值为 0、布尔值为 false、对象引用为 null。然而,只有缺少程序设计经验的人才会这样做。确实,如果不明确地对域进行初始化,就会影响程序代码的可读性。
与局部变量不同,局部变量不会自动的初始化,但是域可以。
无参数的构造器
当你在编写一个类时没有编写构造器,那么系统就会自动提供一个无参构造器,这个构造器将所有的实例域设置为默认值。就像这样:
public Empolyee()
{
name = "";
salary = 0;
hireDay = LocalDate.now();
}
如果类中提供了至少一个构造器,但是没有提供无参数的构造器,则在构造对象时如果没有提供参数就会被视为不合法。
当然,也可以自己编写无参构造器。如果希望所有域被赋予默认值,可以这样编写无参构造器:
public ClassName()
{
}
显式域初始化
在定义类的时候,可以直接将一个值赋值给域。例如:
class Employee
{
private String name = "";
...
}
在构造一个实例时,运行的顺序为:先执行赋值操作,再在构造器中赋值。当一个类的所有构造器都希望把相同的值赋予某个特定的实例域时,这种方式特别有用。
初始值不一定是常量,也可以是静态方法:
class Employee
{
private static int nextId;
private int id = assignId();
...
private static int assignId()
{
int r = nextId;
nextId++;
return r;
}
...
}
调用另一个构造器
关键字 this 表示类方法中的隐式参数。然而,这个关键字还有另一个含义。
如果构造器的第一个语句(必须是第一个语句)形如 this(…),这个构造器将调用同一个类的另一个构造器。下面是一个典型的例子:
public Employee(double s) {
this("Employee #" + nextId, s); // calls Employee(String, double)
nextId++;
}
当调用 new Employee(60000)时,Employee(double)构造器将调用 Employee(String,double)构造器。
采用这种方式使用 this 关键字非常有用,这样对公共的构造器代码部分只编写一次即可。
初始化块
你可以在构造器中设置值,也可以在声明中赋值。你还可以在初始化块中来初始化域:
class Employee {
private static int nextId;
private int id;
private String name;
private double salary;
// object initialization block
{
id = nextId;
nextId++;
}
public Employee(String n, double s) {
name = n;
salary = s;
}
public Employee() {
name = "";
salary = 0;
}
...
}
在这个示例中,无论使用那个构造器,id 域都在对象初始化块中被初始化。初始化块运行在构造器的前面。
值得注意的是,初始化块与显式域初始化有先后关系,例如:
class Employee {
private static int nextId;
// object initialization block
{
id = nextId;
nextId++;
}
private int id = 5;
private String name;
private double salary;
}
使用无参构造器创建一个 Employee
类时,id 域的值为 5
我们已经讲到了很多的初始化数据域的方法,这里来说调用一个构造器,数据域的运行顺序:
- 所以数据域被初始化为默认值(0、false、null)
- 按照在类声明中出现的次序,依次执行所有域初始化语句和初始化块。
- 如果构造器第一行调用了第二个构造器,则执行第二个构造器主体。
- 执行这个构造器的主体。
当然也有静态的初始化块:
// static initialization block
static
{
Random generator = new Random();
nextId = generator.nextInt(10000);
}
静态初始化块,仅仅会加载一次。也就是上述的结果不会随着你创建新的实例而改变。当然,他也和静态初始化语句一样按照顺序执行。
对象析构域 finalize 方法
析构器:与构造器相对,是用来结束对象的声明周期的。
可以为任何一个类添加 finalize 方法。finalize 方法将在垃圾回收器清除对象之前调用。在实际应用中,不要依赖于使用 finalize 方法回收任何短缺的资源,这是因为很难知道这个方法什么时候才能够调用。
如果某个资源需要在使用完毕后立刻被关闭,那么就需要由人工来管理。对象用完时,可以应用一个 close 方法来完成相应的清理操作。