java的override和overload详解

来源:互联网 发布:类似变速齿轮的软件 编辑:程序博客网 时间:2024/06/08 02:37
在详解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的原则:方法名必须相同,参数列表必须不同,其余两个可以相同,也可以不同
原创粉丝点击