Java学习笔记----重写父类方法 super关键字 解决无法将类XXX中的构造器XXX应用到给定类型的问题
父类方法重写
在类的继承关系中,子类会自动继承父类的方法和变量,但经常会需要在子类对某些方法进行修改,在Java中允许子类对父类方法进行重写,但需要注意的是,区别于不是父子类之间方法的重写,这里重写的方法与父方法应具有相同的方法名,参数列表及返回值类型
先看一个例子
hello.java
//package stuJava;
public class hello {
public static void main(String[] args) {
Dog dog = new Dog();//实例化子类Dog
dog.say();
}
}
class Animal{
public void say() {//父类的say()方法
System.out.println("动物的叫声");
}
}
class Dog extends Animal{//Dog类继承父类Animal
public void say() {//重写父类的say()方法
System.out.println("狗的叫声");
}
}
运行如下
可以看到say()方法被重写,而且父类的方法被重写之后,子类不会再去调用也无法访问父类中被重新的方法
*注意子类在重写父类的方法时,不能使用比父类中被重写更严格的访问权限,比如父类中是public,子类就不能写为private
但有时候我们又希望可以访问被重写的方法或变量,Java中提供的super关键字可以解决此问题
super关键字
使用super关键字的格式如下
super.成员方法/变量
还是上面那个例子,稍作修改
hello.java
//package stuJava;
public class hello {
public static void main(String[] args) {
Dog dog = new Dog();//实例化子类Dog
dog.say();
dog.test();
}
}
class Animal{
String name="动物";//父类中定义name
public void say() {//父类中定义say()方法
System.out.println("动物的叫声");
}
}
class Dog extends Animal{//继承父类Animal
String name="狗";//重新赋值给name
public void say() {//重写父类的say()方法
super.say();//访问父类的say()方法
}
void test() {
System.out.println(super.name);//输出的是父类中的name
}
}
运行如下
可以看到super关键字可以访问父类的成员变量和成员方法。
super关键字还可以调用父类的构造方法
super(参数)
同样以此例子,稍作修改
hello.java
package stuJava;
public class hello {
public static void main(String[] args) {
Dog dog = new Dog();//实例化子类Dog
}
}
class Animal{
public Animal(int a) {//定义一个有参的构造方法
System.out.println(a);
}
}
class Dog extends Animal{//继承父类Animal
public Dog() {//Dog的构造方法
super(222);//调用父类的构造方法
}
}
运行如下
通过super调用父类的构造方法必须将其放在子类构造方法的第一行,并且只能出现一次
如果将super(222);删掉
运行报错
在cmd中提示的是 无法将类Animal中的构造器Animal应用到指定类型
原因在于,子类的构造方法一定会调用父类的某一构造方法,通过super可以指定调用哪个父类的构造方法,如果没有指定,则会调用父类无参的构造方法
由于父类已有一个有参(int a)的构造方法,Java不会自动给该类生成无参的构造方法,因此Java编译无法通过,我们需要手动添加无参的构造方法或者显式指定调用有参的构造方法
将上述代码的父类中添加无参的构造方法:
Animal.java
class Animal{
public Animal() {//定义无参的构造方法
System.out.println("无参的构造方法被调用了");
}
public Animal(int a) {//定义一个有参的构造方法
System.out.println(a);
}
}
class Dog extends Animal{//继承父类Animal
public Dog() {//Dog的构造方法
//方法中无代码
}
}
运行如下
可以看到,子类在实例化的时候,默认调用父类无参的构造方法,由此例可以得出
在定义一个类时,手动添加一个无参的构造方法,即使代码为空,这样可以避免继承时出现错误