方法覆盖
Posted yxc-160206
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了方法覆盖相关的知识,希望对你有一定的参考价值。
方法覆盖
方法覆盖的概述
- 方法覆盖又叫做:方法重写,英语单词叫做:Override、Overwrite,都可以。
- 比较常见的叫法:方法覆盖、方法重写、Override。
- 方法覆盖,就是将继承过来的那个方法给覆盖掉了。继承过来的方法没了。
方法覆盖的引入
public class OverrideTest {
public static void main(String[] args) {
Bird b = new Bird(); //创建鸟对象
b.move(); //让鸟儿移动
}
}
class Animal{ //父类
public void move(){ //移动
System.out.println("动物在移动!");
}
}
class Bird extends Animal{ //子类
}
以上程序存在问题:
- 鸟儿在执行
move()
方法的时候,最好输出的结果是:“鸟儿在飞翔” - 但是当前的程序在执行
move()
方法时输出的结果是:“动物在移动” - 很显然
Bird
子类从Animal
父类中继承过来的move()
已经无法满足业务的需求。
子类继承父类时,有一些“行为”可能不需要改进,有一些“行为”可能面临着必须改进。因为父类中继承过来的方法已经无法满足子类的业务需求。
方法覆盖的使用时机
- 子类继承父类之后,当继承过来的方法无法满足当前子类的业务需求时,子类有权利对这个方法进行重新编写,有必要进行“方法的覆盖”。
public class OverrideTest {
public static void main(String[] args) {
Bird b = new Bird();
b.move();
Cat C = new Cat();
C.move();
}
}
class Animal{
public void move(){
System.out.println("动物在移动!");
}
}
class Bird extends Animal{
//对move()方法进行方法覆盖、方法重写
//最好将父类中的方法原封不动的复制过来。(不建议手动编写)
public void move(){
System.out.println("鸟儿在飞翔!");
}
}
class Cat extends Animal{
public void move(){//方法重写
System.out.println("猫在走猫步!");
}
}
使用方法覆盖需满足的条件
- 两个类必须有继承关系
- 重写之后的方法和之前的方法具有:
- 相同的返回值类型
- 相同的方法名
- 相同的形式参数列表
- 访问权限不能更低,可以更高。
- 重写之后的方法不能比之前的方法抛出更多的异常,可以更少。
方法覆盖的重要结论
- 在子类对父类继承过来的方法进行“方法覆盖”之后,子类对象调用该方法的时候,一定执行覆盖之后的方法。
方法覆盖的注意事项
- 方法覆盖只是针对方法,和属性无关。
- 私有方法无法覆盖。
- 构造方法不能被继承,所以构造方法也不能被覆盖。
- 方法覆盖只是针对于实例方法,“静态方法覆盖”没有意义。
- 总结两句话:私有不能覆盖,静态不谈覆盖。
方法覆盖注意事项的解读
静态方法不存在方法覆盖
-
方法覆盖要和多态联合起来使用才有意义
Animal a = new Cat();
a.move();
- 要的是什么结果?
- 编译的时候
move()
方法是Animal
的 - 运行的时候会自动调用子类重写
move()
方法上.
- 编译的时候
- 假如没有多态机制,只有方法覆盖机制,会有意义吗?
- 没有多态机制,方法覆盖也可以没有,如果父类方法无法满足子类业务需求时,子类完全可以定义一个全新的方法。
- 方法覆盖和多态不能分开。
- 要的是什么结果?
-
静态方法存在方法覆盖吗?
- 多态和对象有关,而静态方法的执行不需要对象,所以,一般情况下,我们会说静态方法“不存在”,不探讨静态方法的覆盖。
-
方法覆盖只是针对“实例方法”,“静态方法覆盖”没有意义。
- 这是因为方法覆盖和多态连用才有意义。
-
在方法覆盖中,关于方法的返回值类型。
- 在什么条件满足之后,会构成方法的覆盖?
- 发生具有继承关系的两个类之间。
- 父类中方法和子类重写之后的方法:
- 具有相同的方法名
- 相同的形式参数列表
- 相同的返回值类型
- 在学习多态机制之后:
- “相同的返回值类型”可以修改一下吗?
- 对于返回值类型是基本数据类型来说,必须一致
- 对于返回值类型是引用数据类型来说,重写之后返回值类型可以变得更小。(但意义不大,实际开发中没有人这样写)
- “相同的返回值类型”可以修改一下吗?
- 在什么条件满足之后,会构成方法的覆盖?
私有方法不能覆盖
-
经过测试,私有方法不能覆盖,记住就行
//私有方法不能覆盖 public class OverrideTest05 { private void doSome(){//私有方法 System.out.println("Override‘s private method doSome execute!"); } public static void main(String[] args) { OverrideTest05 ot = new T(); ot.doSome();//Override‘s private method doSome execute! } } class T extends OverrideTest05{ //尝试重写父类中doSome()方法 //访问权限不能更低,可以更高 public void doSome(){ System.out.println("T‘s public doSome method execute!"); } }
方法覆盖的经典案例
- 注意:方法覆盖/重写的时候,建议将父类的方法复制粘贴,这样比较保险。
public class OverrideTest03 {
public static void main(String[] args) {
ChinaPeople p1 = new ChinaPeople();//创建中国人对象
p1.setName("张三");
p1.speak();
AmericPeople p2 = new AmericPeople();//创建美国人对象
p2.setName("Jack");
p2.speak();
}
}
class People {
private String name;
public People() {
}
public People(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void speak() {
System.out.println(name + "正在说话!");
}
}
class ChinaPeople extends People {//中国人
//中国人说汉语
//所以子类需要对父类的speak()方法进行重写
public void speak() {
System.out.println(this.getName() + "正在说汉语!");
}
}
class AmericPeople extends People {//美国人
//美国人说汉语
//所以子类需要对父类的speak()方法进行重写
public void speak() {
System.out.println(this.getName() + " speak English!");
}
}
覆盖0bject
类中的toString()
方法
关于toString()
方法的作用是什么?
- 作用:将“
Java
对象”转换成“字符串的形式”。
Object
类中toString()
方法的默认实现是什么?
public String toString(){
return getClass().getName() + "@" +Interger.toHexString(hashCode());
}
toString
:方法名的意思是转换成String
。含义:调用一个java
对象的toString()
方法就可以将该java
对象转换成字符串的表示。
toString()
方法存在的作用就是:将java
对象转换成字符串形式。
大多数的java
类toString()
方法都是需要覆盖的。因为Object
类中提供的toString()
方法输出的是一个java
对象的内存地址。
至于toString()
方法具体怎么进行覆盖?
- 格式可以自定义,或者听需求的。(听项目要求的)
toString()
方法给的默认实现够用吗?
public class OverrideTest04 {
public static void main(String[] args) {
MyDate t1 = new MyDate();//创建一个日期对象
//调用toString()方法(将对象转换成字符串形式)
//对这个输出结果不满意!希望输出:xxxx年xx月xx日
//重写MyDate的toString()方法之前的结果
//System.out.println(t1.toString());//MyDate@75412c2f
//重写MyDate的toString()方法之前的结果
System.out.println(t1.toString());//1970年1月1日
//当直接输出一个“引用”的时候,println()方法会先自动调用"引用.toString()",
// 然后输出toString()方法的执行结果。
System.out.println(t1);//1970年1月1日
}
}
class MyDate {
private int year;
private int month;
private int day;
public MyDate() {
this(1970, 1, 1);
}
public MyDate(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
//从Object类中继承过来的那个toString()方法已经无法满足业务需求了
//在子类MyDate中有必要对父类的toString()方法进行覆盖/重写
//现在的业务要求是:调用toString()方法进行字符串转换的时候,
//希望转换的结果是:xxxx年xx月xx日,这种格式。
//重写一定要复制粘贴,不要手动编写,会错的
public String toString() {
return year + "年" + month + "月" + day + "日";
}
}
回顾方法重载(overload)
方法重载的使用时机
- 当在一个类当中,如果功能相似的话,建议将名字定义的一样,这样代码美观,并且方便编程。
使用方法重载需要满足的条件
- 在同一个类当中;
- 方法名相同;
- 参数列表不同(个数、顺序、类型)
方法重载和方法覆盖区别
- 方法重载发生在同一个类当中;方法覆盖发生在具有继承关系的父子类当中。
- 方法重载是一个类中,方法名相同,参数列表不同;
- 方法覆盖是具有继承关系的父子类,并且重写之后的方法必须和之前的方法一致:方法名一致、参数列表一致、返回值类型一致。
以上是关于方法覆盖的主要内容,如果未能解决你的问题,请参考以下文章