super关键字
基本介绍
super代表父类的引用,用于访问父类的属性、方法、构造器。
基本语法
1. 访问父类的属性,但不能访问父类的private属性:super.属性名;
2. 访问父类的方法,但不能访问父类的private方法:super.方法名(参数列表);
3. 访问父类的构造器(前面介绍过):super(参数列表); 只能放在构造器的第一句,只能出现一句
细节/好处
1. super调用父类构造器,可以使分工明确。父类属性由父类初始化,子类的属性由子类初始化。
2. 当子类中由和父类中的成员(属性和方法)重名时,为了访问父类的成员,必须通过super。如果没有重名,使用super、this、直接访问是一样的效果(只不过this和直接访问是从本类开始找,super是从父类开始找)。 调用类的属性的规则在上面已经说明过了,调用类的方法的规则与其相同,只不过把属性换成了方法。
子类确实可以写一个与父类完全相同的方法,虽然左边会有隐患提示,但是编译没有问题。
下面对于子类调用父类的方法举一个例子(属性因为很简单就不举例了)
定义一个父类Person:
public class Person { //有四个不同修饰符的方法
public void showName1(){
System.out.println("调用Person的public方法");
}
void showName2(){
System.out.println("调用Person的无修饰符方法");
}
protected void showName3(){
System.out.println("调用Person的protected方法");
}
private void showName4(){
System.out.println("调用Person的private方法");
}
}
定义一个子类Student,先测试在main方法中调用方法(必须用声明的变量调用):
public class Student extends Person{
public static void main(String[] args) {
Student student = new Student();
student.showName1(); //成功调用
student.showName2(); //成功调用
student.showName3(); //成功调用
student.showName4(); //报错,不能调用父类的private方法
}
}
然后在子类的方法中继续测试,由于 this 和 super 都不能在主方法中调用,因此声明一个test方法,在该方法中测试this和super。
public void test(){
this.showName1(); //成功调用
this.showName2(); //成功调用
this.showName3(); //成功调用
this.showName4(); //报错,不能调用private方法
super.showName1(); //成功调用
super.showName2(); //成功调用
super.showName3(); //成功调用
super.showName4(); //报错,不能调用private方法
}
当然,该方法还是需要用main方法中声明的变量调用。
同样的,最重要的一点——在子类调用一个方法时,如果子类没有该方法,会一直向上寻找,如果找到Object类还没有找到,就会报错(super直接忽略本类)。如果在中间找到了一个private的方法,即使上面还有该方法,也不会再寻找了,而是直接报错。
举一个例子:
private void showName1(){ //在Student类中加入一个与Person类同名但不同修饰符的函数
System.out.println("调用Student的private函数");
}
public class Pupil extends Student{ //继承Student
public static void main(String[] args) {
Pupil pupil = new Pupil();
pupil.showName1(); //直接报错,寻找到Student就停了,而不是继续向Person寻找
}
}
3. 如果多个父类中有相同的成员,那么super的访问根据就近原则。
4. super和this的区别
方法重写/覆盖(override)
基本介绍
方法覆盖就是子类有一个方法和父类的某个方法 名称、返回类型、参数一样,这样我们就说子类的这个方法覆盖了父类的那个方法。
使用细节
1. 子类方法的 形参列表,方法名称 要和父类的完全一样。
2. 子类方法的 返回类型 可以和父类方法的返回类型一样,或者是父类返回类型的子类。
public Object showName(){
System.out.println("返回值为Object的父类方法");
return "OK";
} //父类的方法
public String showName(){
System.out.println("返回值为String的子类方法");
return "OK";
} //子类的方法
public static void main(String[] args) {
Student student = new Student();
student.showName(); //调用
}
public String showName(){
System.out.println("返回值为Object的父类方法");
return "OK";
}
public Object showName(){
System.out.println("返回值为String的子类方法");
return "OK";
} //报错
3. 子类方法不能缩小父类方法的访问权限(但扩大可以):public > protected > 默认 > private
public void showName(){
System.out.println("修饰符为public的父类方法");
}
protected void showName(){
System.out.println("修饰符为protected的子类方法");
} //报错,减小了范围
4. 重载和重写的比较