>> 5.5深入构造器
构造器是一个特殊的方法,这个特殊方法用于创建类的实例。Java语言里构造器是创建对象的重要途径(即使使用工厂模式、反射等方式创建对象,其实质依然是依赖于构造器),因此,Java类必须包含一个或一个以上的构造器。
>>5.5.1使用构造界执行初始化
构造器最大的用处就是在创建对象时执行初始化。前面已经介绍过了,当创建一个对象时,系统
为这个对象的属性进行默认初始化,这种默认初始化把所有基本类型的属性设为0(对数值型属性)
或false(对布尔型属性),把所有引用类型的属性设置为null.
如果我们想改变这种默认的初始化,想让系统创建对象时就为该对象各属性显式指定初始值,就
可以通过构造器来实现。
¥注意:
如果程序员没有为Java类提供任何构造器,则系统会为这个类提供一个无参数的构造
器,这个构造器的执行体为空,不做任何事情.无论如何,Java类至少包含一个构造器.
下面类提供了一个自定义的构造器,通过这个构造器就可以让程序员进行自定义的初始化操作
public class TestConstructor { public String name; public int count; //提供自定义的构造器.该构造器包含两个参数 public TestConstructor(String name,int count) { //构造器里的this代表它进行初始化的对象 //下面两行代码将传入的2个奋数赋给this代表对象的name和count属性 this.name = name; this.count = count; } public static void main(String[] args) { //使用自定义的构造器来创建TestConstructor对象 //系统将会对w寸象执行自定义的初始化 TestConstructor tc = new TestConstructor("Struts2权盛指南",20000); //输出TestConstructor对象的name和count属性 System. out.println(tc.name); System. out.println(tc.count); } }
输出:
Struts2权盛指南
20000
运行上面程序,将看到输出TestConstructor对象时,其实name属性不再是null,而count属性也
不再是0.这就是提供自定义构造器的作用。
>> 5.5.2构造器的重载
同一个类里具有多个构造器,多个构造器的形参列表不同.即被称为构造器重载;
构造器重载允许Java类里包含多个初始化逻辑,从而允许使用不同的构造器来初始化Java对象。
构造器重载和方法重载基本相似:要求构造器的名字相同.这一点无须特别要求.因为构造器必
须与类名相同,所以同一个类的所有构造器名肯定相同.为了让系统能区分不同的构造器.多个构造
器的参数列表必须不同。
下面Java类示范了构造器重载,通过构造器重载就可以通过不同的构造器来创建Java对象·
public class ConstructorOverload { public String name; public int count; //提供无参数的构造器 public ConstructorOverload() { } //提供带两个参数的构造器,对该构造器返回的java对象执行初始化 public ConstructorOverload(String name,int count){ this.name=name; this.count=count; } public static void main(String args[]){ //通过无参数构造器创建ConstructorOverload对象 ConstructorOverload oc1 = new ConstructorOverload(); //通过有参数构造器创建ConstructorOverload对象 ConstructorOverload oc2 = new ConstructorOverload("疯狂java",18000); System.out.println(oc1.name + "" + oc1.count); System. out.println(oc2.name + "" + oc2.count); } }
输出:
null0
疯狂java18000
上面的ConswaojOverload类提供了2个重载的构造器,两个构造器的名字相同,但形参列表不同。
系统通过new调用构造器时,系统将根据传入的实参列表来决定调用哪个构造器. 如果系统中包含了多个构造器,其中一个构造器执行体里完全包含另一个构造器的执行体。如图
从图中可以看出,构造器B里完全包含了构造器A,对于这种完全包含的情况,如果是两个方法之间存在这种关系,则可在方法B中调用方法A。但构造器不能直接被调用,构造器必须使用new关键字来调用。但一旦使用new关键字来调用构造器,将会导致系统重新创建一个对象。为了在构造器B中调用构造器A中的初始化代码,又不会重新创建一个Java对象,可以使用this关键字来调用相应构造器。下面代码实现了在一个构造器里直接使用另一个构造器的初始化代码:
public class Apple { public String name; public String color; public double weight; public Apple() { } //两个参数的构造器 public Apple(String name,String color) { this.name=name; this.color=color; } //三个参数的构造器 public Apple(String name,String color,double weight) { //通过this调用另一个重载的构造器的初始化代码 this(name,color); //下面this引用该构造器正在初始化的Java对象 this.weight =weight; } }
上面的Apple类里包含了三个构造器,其中第三个构造器通过this调用来调用另一个重载构造器的初始化代码。程序中this(name,color);调用表明调用该类另一个有2个字符串参数的构造器。
使用this调用另一个重载的构造器只能在构造器中使用,而且必须作为构造器执行体的第一条语句。
使用this调用重载的构造器时,系统会根据this后括号里的实参来调用形参列表与之对应的构造器。
里的代码复制,粘贴到这个构造器里不此可以了吗?
答:如果仅仅从软件功能实现上来看,这样复制、钻贴确实可以实现这个效果,但从软件工程的角度来看,这样做相当糟糕的。在软件开发里有一个规则:不要把相同的代码段书写两次以上!因为软件是一个需要不断更新的产品,如果有一天需要更新图中构遥器A的初始化代码,假设构造器B、构造器C…里都包今了相同的初始化代码,则需要同时打开构造器A、构造器B、构造器C…的代码进行修改;反之,如果构造器B、构造器C··…是通过this调用了构造器A的初始化代码,则只需要打开构造器A进行修改印可。自此,尽量避免相同的代码重复出现,充今复用每一段代码,既可以让程序代码更加简洁.也可以降低软件的瘫痪成本。