方法覆写指的是子类定义了与父类方法名称、参数类型及个数完全相同的方法,凡是被覆写的方法不能拥有比父类更严格的访问控制权限。
范例:观察简单的方法覆写
class Person {
public void printInfo() {
System.out.println("【Person类】printInfo()方法") ;
}
}
class Student extends Person {
public void printInfo() { // 注意方法名完全相同
System.out.println("【Student类】printInfo()方法") ;
}
}
public class TestDemo {
public static void main(String args[]) {
Student stu = new Student() ; // 子类实例化对象
stu.printInfo();
}
}
使用覆写时一定要关注以下两点
再次强调:凡是被覆写的方法不能拥有比父类更严格的访问控制权限
private
< default
< public
public
权限,子类方法只能是public
权限;如果父类default
权限,子类可以是default
、public
。
private
权限,如果父类方法被private定义,那么表示该方法只能被父类调用,对子类而言根本没有这个方法。class Person {
void printInfo() { // default权限
System.out.println("【Person类】printInfo()方法") ;
}
}
class Student extends Person {
private void printInfo() { // 访问权限变严格了
System.out.println("【Student类】printInfo()方法") ;
}
}
public class TestDemo {
public static void main(String args[]) {
Student stu = new Student() ; // 子类实例化对象
stu.printInfo();
}
}
//输出:错误提示: Student中的printInfo()无法覆盖Person中的printInfo()
class Person {
public void method(){
this.printInfo() ;
}
private void printInfo() {
System.out.println("【Person类】printInfo()方法") ;
}
}
class Student extends Person {
// 这时这个方法只是子类定义的新方法,和父类一点关系没有
public void printInfo() {
System.out.println("【Student类】printInfo()方法") ;
}
}
public class TestDemo {
public static void main(String args[]) {
Student stu = new Student() ; // 子类实例化对象
stu.method();
}
}
// 这时输出为:【Person类】printInfo()方法
// 如果把父类方法private换为default或public,输出为:【Student类】printInfo()方法
结论:绝大多数情况下写重载时访问权限就用public。
请回顾:《阿里云【名师课堂】Java面向对象开发8:构造方法与匿名对象》中的方法重载部分。
区别 | 重载 | 覆写 |
---|---|---|
英文 | Overload | Override |
概念 | 方法名称相同,参数的种类、个数不同 | 方法名称、返回值类型、参数类型及个数完全相同 |
范围 | 发生在一个类中 | 发生在继承关系中 |
限制 | 没有权限要求 | 凡是被覆写的方法不能拥有比父类更严格的访问控制权限 |
当子类定义了与父类中属性名称完全相同的属性时就叫做属性的覆盖。
class Person {
public String info = "it was called yellow" ;
public void printInfo() {
System.out.println("【Person类】printInfo()方法") ;
}
}
class Student extends Person {
public int info = 3000 ;
public void printInfo() {
System.out.println(info) ;
}
}
public class TestDemo {
public static void main(String args[]) {
Student stu = new Student() ; // 子类实例化对象
stu.printInfo() ;
}
}
这个操作实际上没有意义,因为在实际操作中我们会用private定义属性,这时子类根本不知道父类中有哪些属性,也就不存在对父类属性进行重载操作。
结论:写属性时尽量不要有重名。
在之前的子类对象实例化操作的讲解时介绍了super(),当时是子类调用父类方法时才使用。
那么在进行覆写的操作过程中,子类也可以使用super.方法()
或者super.属性
明确调用父类的方法或属性。
范例:观察一个程序
class Person {
public void printInfo() {
System.out.println("【Person类】printInfo()方法") ;
}
}
class Student extends Person {
public void printInfo() {
System.out.println("【Student类】printInfo()方法") ;
}
}
public class TestDemo {
public static void main(String args[]) {
Student stu = new Student() ; // 子类实例化对象
stu.printInfo() ;
}
}
对于这段程序,输出是:【Student类】printInfo()方法。
stu
,然后stu
调用子类中的printInfo
方法。printInfo
方法。如果实例化操作改为:Person stu = new Person() ;
,输出是:【Person类】printInfo()方法。
printInfo
方法。如果将子类改为:
class Student extends Person {
public void printInfo() {
printInfo() ; // this.printInfo() ;
System.out.println("【Student类】printInfo()方法") ;
}
}
输出为:java.lang.StackOverflowError,即栈溢出。
printInfo() ;
就相当于this.printInfo() ;
。printInfo() ;
中调用printInfo() ;
。如果将子类改为:
class Student extends Person {
public void printInfo() {
super.printInfo() ;
System.out.println("【Student类】printInfo()方法") ;
}
}
输出为:
为什么?
printInfo() ;
再输出自己的printInfo() ;
。范例:观察调用父类属性
先回顾第58讲中的属性覆盖程序,子类中的System.out.println(info) ; // info=this.info
语句输出的永远是3000,因为它输出的是自己的info。
要想输出父类的info应该:在子类的printInfo
方法中添加:System.out.println(super.info) ;
通过分析我们发现:super与this的使用形式上高度相似,但是二者最大区别在于:super是子类访问父类的操作,this是在本类自身中访问处理的操作。
区别 | this | super |
---|---|---|
概念 | 访问本类中的属性、方法 | 由子类访问父类中的属性、方法 |
查找范围 | 先查找本类,如果本类没有则调用父类 | 不查找本类,直接调用父类 |
特殊 | 表述当前对象 | 没有类似“表示父类对象”的概念 |
原文:https://www.cnblogs.com/playerone/p/13125292.html