super 关键字
keyword 是“关键字”的意思,顺便补一下英语。
为什么会有这个关键字的出现呢?
存在肯定有理!
鱼除了想有自己的呼吸方式以外,它还想要Animal的呼吸方式,该怎么办呢?你可能会在鱼的breath方法中是用new Animal().breath();不就是可以了吗?当然这个也可以,但是这样很麻烦啊!
java中提供的特殊变量super,super代表父类,它提供了访问父类当中被覆盖的方法的机制。
class Fish extends Animal {
public void breath() {
super.breath();
System.out.println("fish bubble");
}
}
特殊变量super,提供了对父类的访问。
每个子类构造函数的第一条语句,都是隐含的调用super()(条件:父类只有无参构造函数,或者显示的写了一个无参构造函数)。
强烈建议:只要创建一个类,那么就毫无怀疑的将它的无参构造函数写上,不论今后是否能用上。
public class Car { public Car() { System.out.println("Car constract"); } }
class Bus extends Car { public Bus() { System.out.println("Bus constract"); }
public static void main(String[] args) { Bus b = new Bus(); // 只实例化派生类 } } |
|
运行结果如下: |
|
G:\java>javac Car.java G:\java>java Bus Car constract Bus constract |
只实例化派生类,导致父类的构造函数也被调用。并且在子类构造函数调用之前。说明在子类的构造函数中隐含了super()。Bus是Car的一个子类,当去实例化子类的时候,当然要先实例化父类对象,没有父亲就没有孩子。 |
如果父类没有这种形式的构造函数,那么在编译的时候就会报错。
public class Car {
public Car(int a) {
System.out.println("Car constract");
}
}
class Bus extends Car {
public Bus() {
System.out.println("Bus constract");
}
public static void main(String[] args) {
Bus b = new Bus();
}
}
原因是:
public Bus() {
System.out.println("Busconstract");
}// 在这个构造方法中找到一个super();然而父类并没有一个无参的构造方法,因此super();就不能成功的指向父类的一个具体的构造方法了,所以会报告编译时错误。那么修改方式是:在父类提供一个不带参数的构造方法,或者在子类的构造方法中加一个带参数的super(3);即可。
方法能够被继承,但是构造方法是不能被继承的。
public Bus() {
Car(10);// error 构造方法是不能被继承的。
System.out.println("Bus constract");
}
如果父类中声明了含参的构造方法,而子类中没有写构造方法,那么会报告错误。
class A {
public A(String s) {
System.out.println(s);
}
}
class B extends A {
}
这个错误实际上是这样的:类B中有一个无参数的构造方法public B() {},而这个构造方法中有一个super()指向了父类的无参构造方法,但是父类没有这个无参构造方法。只有一个public A(String s) {System.out.println(s);}构造方法,所以B中的super()找不到父类的无参构造函数,于是报告异常。
解决方案:
1、在B中写一个和父类参数类型相同的构造方法,然后将这个参数传递给父类。
public class B extends A{
public B(String sb) {
super(sb);
}
}
2、在父类当中增加一个无参的构造方法
public class A {
public A() {
}
public A(String sa) {
System.out.println(sa);
}
}
3、其实和方案1类似
public class B extends A{
public B() {
super("");
}
}