java的override和overload详解

在详解override和overload前需要对多态做一个详细的了解


什么是多态?
多态的教科书标准定义:允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。其实可以借助于生活中的常见的一种多态现象来解释多态:比方说按下 F1 键这个动作,如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;如果当前在 Word 下弹出的就是 Word 帮助;在 Windows 下弹出的就是 Windows 帮助和支持。同一个事件发生在不同的对象上会产生不同的结果。


实现多态的技术
在java中,实现多态的两种方式为override重写和overload重载,而最终实现的技术为:动态绑定(dynamic binding),指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法


多态->晚绑定
多态是一种运行期的行为,不是编译期的行为。


多态的方法访问原理
虽然说父类的引用指向的是子类的对象,但是最终该引用还是父类,当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,就会去查找子类中是否有同名方法,如果没有,则调用父类的该方法;如果有,则会判断是否满足重写的两同两小一大原则,如果满足,则调用子类的该方法;如果不满足,则编译器报错;
多态访问的方法访问测试案例
//test1 子类中没有该同名方法
class fun{
    public void mi() throws NullPointerException{

        System.out.println("fa mi ...");
    }
}
public class overrideTest extends fun{

    public static void main(String[] args) {
        fun f = new overrideTest();
        f.mi();
    }
}
//test1的最终输出结果为:fa mi... 调用的是父类的mi方法

//test2  子类中重写了父类的方法
class fun{
    public void mi() throws Exception{

        System.out.println("fa mi ...");
    }
}
public class overrideTest extends fun{

    public void mi() throws NullPointerException{
        System.out.println("over mi...");
    }

    public static void main(String[] args) throws Exception {
        fun f = new overrideTest();
        f.mi();
    }
}
//test2中因为子类有同名方法,并且满足两同两小一大原则,所以运行正常,输出 over mi..调用的是子类的mi方法

//test3 子类有该同名方法,但是不满足override原则
class fun{
    public void mi() throws NullPointerException{

        System.out.println("fa mi ...");
    }
}
public class overrideTest extends fun{

    public void mi() throws Exception{
        System.out.println("over mi...");
    }

    public static void main(String[] args) throws Exception {
        fun f = new overrideTest();
        f.mi();
    }
}
//test3中子类有该同名方法,但是不遵循重写原则(子类抛出的异常大于父类),因此在编译期就会进行报错

//test4 父类中并没有该方法,但是子类中有该方法
class fun{
}
public class overrideTest extends fun{

    public overrideTest mi() throws NullPointerException{
        System.out.println("over mi...");
        return null;
    }

    public static void main(String[] args) throws Exception {
        fun f = new overrideTest();
        f.mi();
    }
}
//test4中程序也会在编译期报错,因为虽然父类的引用是指向子类的对象,但是最终还是父类类型引用,依旧是父类对象在进行调用,而在test4中父类并没有该方法,子类的方法只是属于子类,并不能扩展父类,所以将会报错
言归正传,现在来说说override和overload


override
重写,是子类对父类的特定方法一种修改,是父类和子类之间的多态的实现


override原则(两同两小一大)
两同:方法名相同,参数列表相同
两小:子类方法返回值小于等于父类;子类抛出的异常小于等于父类
一大:子类方法的修饰符访问权限大于等于父类


代码重点解析override原则->两小
首先我们来看,子类方法的返回值小于等于父类,这里注意的是,如果返回值是基本数据类型,就必须要相等;如果为引用类型的话,可以小于,即子类的返回类型可以是父类返回类型的子类,即在返回值上面进行了多态;
//测试方法返回值小于
class fun{
    protected fun mi() throws Exception{

        System.out.println("fa mi ...");
        return null;
    }
}
public class overrideTest extends fun{

    public overrideTest mi() throws NullPointerException{
        System.out.println("over mi...");
        return null;
    }

    public static void main(String[] args) throws Exception {
        fun f = new overrideTest();
        f.mi();
    }
}
//代码运行正常
接下来我们来看看下一个:子类方法抛出的异常要小于等于父类,这是为什么呢,从一个很简单的方面进行解释:当我们定义一个需要抛出异常的方法时,我们在main方法(所有的方法)进行调用该方法时,都是需要抛出该方法对应的异常的,而因为引用类型是父类,所以最终main方法中抛出的异常是与父类的该方法一致的,而这个时候子类对该方法进行重写了,所以实质上调用的是子类的方法,如果这个时候子类抛出的异常范围大于父类时,那么就会导致异常捕获失败,不成立;因此,子类重写的方法抛出的异常是要小于等于父类的;
//代码和test相同,main中抛出的异常与fun.mi一致


代码重点解析override原则->一大
这里一大指的是:子类的方法访问权限要大于等于父类,试想一下,在运行时,我们真正调用的是子类重写后的方法,如果这个时候子类的方法我们没有权限,就只能访问父类的该方法了,从而不符合重写调用,不成立;所以子类的访问权限要大于等于父类的,目的是比父类原生方法有更大的权限进行调用,父类原生方法可以调用的地方都可以调用子类重写后的方法;
//代码同test4,父类使用protected、子类使用public进行修饰


overload重载
重载发生在一个类的内部,主要用于实现类对象的多态;


重载的原则
方法名必须相同;
参数列表必须不相同,参数列表或者参数个数任一个不同即可(参数之间为父子关系也算不同,int 和Integer也算不同)
方法的修饰符和返回值可以相同,也可以不相同;


代码重点解析overload原则
一个方法的定义,主要由:访问权限控制符+方法返回值+方法名+参数列表组成,对于重载来说,不管访问权限控制符和方法返回值是否相等,它都必须满足:方法名相同、参数列表不同,即使前面两者都不同,也需要满足这两个条件
//错误的重载
public class overrideTest extends fun{

    public overrideTest mi() throws NullPointerException{
        System.out.println("over mi...");
        return null;
    }
    private int a(String s){   //1.
        return 1;
    }
    public double a(String s){    //2.
        return 2;
    }
    public static void main(String[] args) throws Exception {
        overrideTest t = new overrideTest();
        System.out.println(t.a("!1"));
    }
}
//错误原因:虽然1.和2.的访问权限控制符和返回值不相等,但是他的参数列表和方法名是相等的,所以这两个方法仍然看做是同一个方法,不满足重载的条件,编译会报错


总结
多态的两种实现方式: override+overload
多态是一种晚绑定,最终的对象引用是在运行期进行确定,编译期还不能确定
虽然多态实现父类的引用指向的是子类的对象,但是真正的调用还是在父类中发生
override的原则:两同两小一大
overload的原则:方法名必须相同,参数列表必须不同,其余两个可以相同,也可以不同
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值