刚睡完午觉起来,有点迷糊,然后接着练习Java中元组(tuple)的时候突然就遇到这么个问题,关于继承的问题,奇怪在睡觉之前怎么就没发现这个问题呢,传说中的“面向睡一觉编程”吗。。。Orz
先贴上代码:
首先是创建一个父类文件TwoTuple.java
package test.fifth;
public class TwoTuple<A, B> {
public A first;
public B second;
public TwoTuple(A a, B b) {
first = a;
second = b;
}
public String toString() {
return "( " + first + "," + second + " )";
}
}
接下来是子类文件ThreeTuple.java
package test.fifth;
public class ThreeTuple<A, B, C> extends TwoTuple<A, B> {
public C third;
public ThreeTuple(A a, B b, C c) {
super(a, b);
third = c;
}
public String toString() {
return "(" + first + "," + second + "," + third + ")";
}
}
当然,现在这两个类都没有问题。
但是当我将ThreeTuple类的构造方法中的super(a,b)删除后,就会报一个错误,如下:
Implicit super constructor TwoTuple< A,B >() is undefined. Must explicitly invoke another constructor
翻译下:隐式的父类构造方法TwoTuple< A,B >是未定义的,必须显示的调用另一个构造方法。
下面整理下错误:当我使用子类ThreeTuple时,在其构造方法中没有调用父类的构造方法,这时候编译器报错,难道子类继承父类时,必须调用父类的构造方法吗?
然后,试着找找解决办法,根据报错,自然想到在父类(TwoTople)中寻找线索,果然,
在我删除子类构造方法中的super(a,b)后,再到父类中,增加个默认构造方法之后,错误就消失了,如下:
TwoTuple.java
public TwoTuple() {
}
什么?默认构造方法不是应该编译器自动添加的吗?这里怎么会需要手动添加呢?不科学啊啊啊。。。难道是还没睡醒?赶紧给自己两耳光清醒清醒。。。
好吧,清醒过来还得继续找出原因
下面是经过一番搜索找到的解答整理:
默认构造方法的概念:
默认构造方法是没有参数的构造方法,可以简单的分为两种:
(1) 隐式的默认构造方法
(2) 显式定义的构造方法
在java语言中,每个类至少有一个构造方法,为了保证这一点,如果用户定义的类中没有构造方法,那么java语言将自动提供一个隐含的默认构造方法,该构造方法没有参数,用public修饰,没有返回值,并且方法体为空,例如:
public TwoTuple(){
}
当然在程序中也可以明确的定义默认构造方法,
如果在类中定义了一个或者多个构造方法,并且所有的构造方法都有参数,这个类就失去了默认的构造方法(!!!整个问题的关键就在这里!!!)。如果想保留默认的构造方法,必须显式的定义出来。例如:
public class TwoTuple<A, B> {
public A first;
public B second;
public TwoTuple(A a) {
System.out.println(a);
}
public TwoTuple(A a, B b) {
System.out.println(a + "," + b);
};
}
对于这个类,如果要定义一个对象 TwoTuple test = new TwoTuple() 这个就是错误的,因为这样定义是通过默认无参构造方法进行初始化,但是在这个类中没有这个构造方法,如果想这样定义,必须显式的定义默认无参构造方法。
子类调用父类的构造方法:
父类的构造方法不能被子类继承(这里回答了标题的问题),但是在子类对象被创建时,如果不显式调用父类的构造方法,这时子类会调用父类的无参构造方法,如果父类没有无参构造方法(也就是如上面所述),则Java编译器将报告错误。如果要调用父类的其他构造方法(带参构造方法),必须出使用super显式的指
使用super必须遵循以下规则:
(1) 在子类的构造方法中不能直接使用父类的构造方法名称直接调用,而必须使用super语句
(2) 如果在子类的构造方法中时用super调用父类的构造方法,他必须作为构造方法的第一条语句出现。
总结:在创建子类的对象时,java虚拟机首先执行父类的构造方法,然后再执行子类的构造方法,在多重继承的情况下,将从最顶层的类的构造方法开始执行,然后依次执行各个类的构造方法
以上,一觉醒来还学到不少东西,哈哈,以后要多睡觉!!!