重载和重写的编码区别及JVM编译区别

来源:互联网 发布:中企动力域名管理 编辑:程序博客网 时间:2024/05/22 01:51

一、在代码层次重载和重写的区别如下:

重载:

        1、重载的方法间方法名相同,参数的个数及类型不相同,参数及其类型表不相同即可(参数类型的顺序不同,参数类型个数及参数个数相同亦可);

        2、不能通过访问权限、返回值及抛出异常进行重载;

        3、方法的异常类型及数目不会对重载造成影响;

重写:

        1、存在于子类中,是对父类方法的覆盖;

        2、重写的方法,方法名、参数表个数、类型及顺序必须与父类被重写方法完全一样;

        3、重写方法的修饰符一定要大于被重写方法的修饰符:public>protected>default (private 方法无法被子类获取,不构成重写);

        4、重写方法的返回值必须与被重写方法一致;

        5、重写方法不能比被重写方法的抛出检查范围广泛的检查异常,例如被重写方法的抛出异常为:IndexOutOfBoundsException,重写方法的异常不能是:Exception;

        6、静态方法不能被重写,如果子类存在于父类完全相同的静态方法,那么会将父类的此方法隐藏,具体调用那个方法,要看声明;

        7、重写方法增加注解:@Override 后会自动做如上的重写检查


引用及参考:

http://blog.csdn.net/ycb1689/article/details/17163273;(静态方法重写的解析很到位)

http://www.iteye.com/problems/99162;(不完整,参考了此文回答的重写异常部分)

http://blog.csdn.net/baggio7095586/article/details/6149261(存在错误,代码层次的区别基于此在验证后得出的结论。)


二、JVM编译基础上的区别:

重载:

        1、JVM中对此方法调用的解析方法为静态分派:使用的是invokespecial;

重写:

        1、JVM对重写的方法的解析为动态分派:使用的是invokevirtual;体现效果为,当父类方法被重写后,无论声明和初始化的是子类还是父类,最终处理的都是重写的方法;


说明如下:

1、方法调用的解析
        在Class文件中,方法调用是常量池中的一个符号引用,在加载的解析期或者运行时才能确定直接引用。
        下面两种指令是在解析期就可以确定直接引用,调用的对应方法也叫作非虚方法。
a、  invokestatic 主要用于调用静态方法
b、  invokespecial 主要用于调用私有方法,构造器,父类方法。

        下面两种是在运行时才能确定直接引用的,但是除了final方法,final方法也可以在解析期确定方法的调用版本。
a、  invokevirtual 虚方法,不确定调用那一个实现类
b、  invokeinterface 接口方法,运行时才能确定实现接口的对象。

2、动态分派
        先回顾一下静态和动态分派的概念。Java中,所有以静态类型来定位方法执行版本的分派动作,都称为静态分派。其实也就是重载(Overload)就是一种典型的静态分派,在编译期就可以知道方法调用的实际版本。相对得,动态分派是需要在运行期才能确定方法的版本,也就是直接引用,一种典型应用就是重写(OverWrite)。在调用invokevirtual指令时,把常量池中的类方法符号引用解析到直接引用的过程就是重写的过程,运行期根据实际类型确定方法的执行版本。

3、重写JVM解析图:

     这个是类被虚拟机加载进方法区之后,在方法区里面的布局。

         如果我们像上面那样,用一个基类引用指向子类对象,那么,这个引用所绑定的类还是子类。只不过它所能访问的虚方法表与一般子类对象不同。上面黄色的部分才是父类这个引用所能访问的vtable的范围(关于vtable的生成有时间在总结),而普通的子类引用可以访问整个子类的vtable。


引用及参考:

http://yunshen0909.iteye.com/blog/2231374;(此文通过对字节码的解读,清楚的划分了重载是静态分派,重写是动态分派)

http://blog.csdn.net/qc_liu/article/details/42584099;(清晰的解析了重写的JVM实现逻辑)



0 0
原创粉丝点击