super关键字
super代表父类的引用,用于访问父类的属性、方法、构造器。
基本语法:
访问父类的属性:
不能访问父类中private
修饰的属性
super.属性名;
访问父类的方法:
不能访问父类中private
修饰的方法
super.方法名(参数列表);
访问父类的构造器:
super(参数列表);
只能放在构造器的第一句,只能出现一句。
super深入
在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。目的在于子类对象中包含了其对应的父类空间,便可以包含其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员。
调用父类构造器的好处: 分工明确,父类属性由父类初始化,子类属性由子类初始化
当子类中的成员(属性和方法)与父类中的成员重名时,为了访问父类的成员,必须使用super。
如果没有重名,那么使用super、this、直接访问的效果是一样的。
如果不使用super关键字调用方法,找方法时的顺序是,如果本类有,并且可以调用,那么就调用本类的,如果没有或者不可调用,会往父类找,直到找到可以调用的为止。
如果使用super关键字调用方法,就会依次去父类找,找不到或者不可以调用就会报错,直到找到为止,不会调用本来的方法。
super的访问不限于父类,可以使用super访问父类的父类的成员。如果重名的话则遵循就近原则。
class Animal {
public void eat() {
System.out.println("animal : eat");
}
}
class Cat extends Animal {
public void eat() {
System.out.println("cat : eat");
}
public void eatTest() {
this.eat(); // this 调用本类的方法
super.eat(); // super 调用父类的方法
}
}
public class ExtendsDemo08 {
public static void main(String[] args) {
Animal a = new Animal();
a.eat();
Cat c = new Cat();
c.eatTest();
}
}
输出结果为:
animal : eat
cat : eat
animal : eat
super和this的区别
区别点 | this | super |
---|---|---|
访问属性 | 访问本类中的属性,如果本类中没有此属性,则从父类中继续查找,直到找到为止,否则编译失败 | 访问父类的属性,直接从父类中查找,直到找到为止,否则编译失败 |
调用方法 | 访问本类中的方法,如果本类中没有此方法,则从父类中继续查找,直到找到为止,否则编译失败 | 直接访问父类中的方法,直到找到为止,否则编译失败 |
调用构造器 | 调用本类的构造器,必须放在构造器的首行 | 调用父类构造器,必须放在子类构造器的首行 |
特殊 | 表示当前对象 | 子类中访问父类对象 |
方法重写
如果子类父类中出现重名的成员方法,这时的访问是一种特殊情况,叫做方法重写(Override)。
重写(Override): 子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写或者复写。声明不变,重新实现。
class Fu {
public void show() {
System.out.println("Fu show");
}
}
class Zi extends Fu {
//子类重写了父类的show方法
public void show() {
System.out.println("Zi show");
}
}
public class ExtendsDemo05{
public static void main(String[] args) {
Zi z = new Zi();
// 子类中有show方法,只执行重写后的show方法
z.show(); // Zi show
}
}
子类方法覆盖父类方法,必须要保证权限大于等于父类权限。子类方法覆盖父类方法,返回值类型、函数名和参数列表都要一模一样。
方法重写的返回值类型
子类方法的返回类型和父类方法的返回类型要一样,或者是父类返回类型的子类如果子类的返回类型不是父类的返回类型或者父类返回类型的子类,但是方法名和参数列表相同,则编译出错
比如,hi方法构成了重写,String
是Object
的子类
public class A {
public Object hi() {}
}
class B extends A {
public String hi() {}
}
方法重写的访问权限
子类方法不能缩小父类方法的访问权限比如父类有一方法的权限修饰符是
public
,那么子类重写的方法的权限修饰符也只能是public
public class A {
Object hi() {}
}
class B extends A {
// 只能比A类中的hi方法权限大,不能小
public String hi() {}
}
重写和重载的区别
名称 | 重载(overload) | 重写(override) |
---|---|---|
发生范围 | 本类 | 父子类 |
方法名 | 必须一样 | 必须一样 |
形参列表 | 类型、个数或者顺序至少有一个不同 | 相同 |
返回类型 | 无要求 | 子类重写的方法,返回类型必须和父类一样,或者是父类该方法返回类型的子类 |
修饰符 | 无要求 | 子类重写的方法的权限修饰符必须大于等于父类的权限修饰符,不能缩小访问范围 |