继承以前博客都有介绍,这里就不再赘述了。
1、先看构造函数的基本内容
构造函数是一个类创建的根本途径,如果一个类没有构造函数,那么这个类通常将无法创建实例。所以Java提供了一个功能:如果没有自定义构造函数,系统会默认生成一个无参无构造方法无返回值的构造函数;如果有自定义的构造函数,系统不再生成默认的构造函数。
构造函数的语法格式:[修饰符] 属性类型 属性名 [= 默认值]
修饰符:可以是default(即省略不写)、public、protected、private、static、final,其中public、protected、private三个最多只能出现其中一个,可以与static、final组合起来修饰属性。
属性类型:可以是Java允许的所有数据类型。
属性名:合法的标识符即可。【合法的标识符:以字母、下划线、美元符开始,后接字母、下划线、美元符、数字】但一般应考虑程序的可读性,首单词的首字母小写,后续单词的首字母都大写。
默认值:可写可不写。
构造函数的返回值和参数都可有可没有,但是名字必须和类的名字相同。这样就会带来一个问题:当使用继承的时候,子类是否继承父类的构造函数?如果继承,那么子类的构造函数应该是怎样的(毕竟父类和子类不同名,而构造函数要求是同名的)?
2、子类对父类构造函数的继承
通过程序实例来研究这个问题。
/*2014-09-11 15:47
* 研究Java中构造函数的继承
* */
class A{
int i;
public A(){
System.out.println("A()");
}
public A(int i){
System.out.println("A(int i)");
}
}
class B extends A{
// public A(){ //【不可以重写父类的构造函数】
// System.out.println("A()");
// }
// public A(int i){
// System.out.println("A(int i)");
// }
public B(){
System.out.println("B()");
}
public B(int i){
System.out.println("B(int i)");
}
}
public class TestConstructedFunction {
public static void main(String[] args) {
B b1 = new B();
B b2 = new B(1);
}
}
该问题存在四大类,共16种情况,所得结果如下所示:
子类 组合情况
父类 |
无 |
无参 |
有参 |
无参,有参 |
无 | B()无错 B(1)编译错误 | B()无错 B(1)编译错误 | B()编译错误 B(1)无错 | B()无错, B(1)无错 |
无参 | B()无错 B(1)编译错误 | B()无错 B(1)编译错误 | B()编译错误 B(1)无错 | B()无错 B(1)无错 |
有参 | 构建子类B出错 | 构造函数B()出错 | 构造函数B(int i)出错(父类没有A()构造函数) | B()无错 B(1)无错 |
无参,有参 | B()无错 B(1)编译错误 | B()无错 B(1)编译错误 | B()编译错误 B(1)无错 | B()无错 B(1)无错 |
其中,“无”表示没有自定义构造函数,“无参”表示只有自定义的无参构造函数,“有参”表示只有自定义的有参构造函数,“有参,无参”表示有自定义的无参和有参构造函数。
分析:
0、子类不能够重写父类的构造函数;
1、当父类没有自定义构造函数时,子类的构造函数可以随意构建;
2、当父类只自定义了无参构造函数时,子类的构造函数可以随意;
3、当父类只自定义了有参构造函数时,构建子类出错;
4、当父类自定义了有参和无参构造函数时,子类的构造函数可以随意构建;
5、生成子类对象时,不管调用何种构造函数(有参/无参),系统都会默然先调用父类的无参构造函数(super.()),再执行子类操作。
由上述分析,可得出如下结论:
1、子类不能够重写父类的构造函数;
2、父类中必须有无参的构造函数(自定义/系统默认),不然构建子类会编译出错;
3、生成子类对象时,不管调用何种构造函数(有参/无参),系统都会默然先调用父类的无参构造函数(super.()),再执行子类操作。【对应第2条可知为何父类必须有无参构造函数】
因此,若不想被父类的构造函数干扰,最好将父类的构造函数写成无返回值无参无方法体的格式。