简易Java(16):Java中的覆盖和重载
1、定义
对于Java初学者来说,覆盖(Overriding)和重载(Overloading)是两个非常容易混淆的概念。
重载的情况是这样的,在同一个类中,有两个甚至更多的方面,他们名称相同,但是有不同的参数列表。
覆盖的意思是,有两个同名的方法,同时还有相同的参数列表,但是却有不同的实现。其中一个存在于父类中,另外一个在子类中。
2、覆盖 vs 重载
对于覆盖和重载有几个非常重要的事实需要注意:
- 真实的对象类型,而不是引用变量的类型,至于哪个覆盖方法会被使用是在运行时决定的;
- 引用类型在编译时决定那个重载方法被使用;
- 多态性取决于覆盖,而不是重载。
3、覆盖示例
这里有一个覆盖的示例。阅读代码,然后猜测将要输出什么?
01 | package com.diguage.books.simplejava.ar16.v1; |
02 |
03 | /** |
04 | * 覆盖示例一:父类 |
05 | * <p/> |
06 | * Coder:D瓜哥,http://www.diguage.com/ |
07 | * <p/> |
08 | * Date: 2014-11-16 10:08 |
09 | */ |
10 | public class Dog { |
11 | public void bark() { |
12 | System.out.println( "woof " ); |
13 | } |
14 | } |
01 | package com.diguage.books.simplejava.ar16.v1; |
02 |
03 | /** |
04 | * 覆盖示例一:子类 |
05 | * <p/> |
06 | * Coder:D瓜哥,http://www.diguage.com/ |
07 | * <p/> |
08 | * Date: 2014-11-16 10:12 |
09 | */ |
10 | public class Hound extends Dog { |
11 | public void sniff() { |
12 | System.out.println( "sniff " ); |
13 | } |
14 |
15 | @Override |
16 | public void bark() { |
17 | System.out.println( "bowl" ); |
18 | } |
19 | } |
01 | package com.diguage.books.simplejava.ar16.v1; |
02 |
03 | /** |
04 | * 覆盖示例一:Main类 |
05 | * <p/> |
06 | * Coder:D瓜哥,http://www.diguage.com/ |
07 | * <p/> |
08 | * Date: 2014-11-16 10:15 |
09 | */ |
10 | public class OverridingMain { |
11 | public static void main(String[] args) { |
12 | new Hound().bark(); |
13 | ((Dog) new Hound()).bark(); |
14 | // ((Dog)new Hound()).sniff(); |
15 | } |
16 | } |
输出如下,你猜对了吗?
1 | bowl |
2 | bowl |
一个更好的例子:
01 | package com.diguage.books.simplejava.ar16.v2; |
02 |
03 | /** |
04 | * 覆盖示例二:父类Animal |
05 | * <p/> |
06 | * Coder:D瓜哥,http://www.diguage.com/ |
07 | * <p/> |
08 | * Date: 2014-11-16 10:19 |
09 | */ |
10 | public class Animal { |
11 | public void stinky() { |
12 | System.out.println( "stinky animal !" ); |
13 | } |
14 | } |
01 | package com.diguage.books.simplejava.ar16.v2; |
02 |
03 | /** |
04 | * 覆盖示例二:子类Cow |
05 | * <p/> |
06 | * Coder:D瓜哥,http://www.diguage.com/ |
07 | * <p/> |
08 | * Date: 2014-11-16 10:22 |
09 | */ |
10 | public class Cow extends Animal { |
11 | @Override |
12 | public void stinky() { |
13 | System.out.println( "stinky cow !" ); |
14 | } |
15 | } |
01 | package com.diguage.books.simplejava.ar16.v2; |
02 |
03 | /** |
04 | * 覆盖示例二:子类Dog |
05 | * <p/> |
06 | * Coder:D瓜哥,http://www.diguage.com/ |
07 | * <p/> |
08 | * Date: 2014-11-16 10:20 |
09 | */ |
10 | public class Dog extends Animal { |
11 |
12 | @Override |
13 | public void stinky() { |
14 | System.out.println( "stinky dog !" ); |
15 | } |
16 |
17 | public void bark() { |
18 | System.out.println( "wow wow!" ); |
19 | } |
20 | } |
01 | package com.diguage.books.simplejava.ar16.v2; |
02 |
03 | /** |
04 | * 覆盖示例二:Main类 |
05 | * <p/> |
06 | * Coder:D瓜哥,http://www.diguage.com/ |
07 | * <p/> |
08 | * Date: 2014-11-16 10:23 |
09 | */ |
10 | public class Main { |
11 | public static void main(String[] args) { |
12 | Animal obj = new Dog(); |
13 | obj.stinky(); |
14 | } |
15 | } |
当你像上面那样创建对象并调用方法时:
1 | Animal obj = new Dog(); |
2 | obj.stinky(); |
编译器要做的就是检查对象类型,对于这个例子就是Animal
。然后检查在Animal
中是否定义stinky()
方法。请注意,在运行时才创建对象。所以,编译器不知道Dog
的stinky()
方法是否被调用。所以,在编译时,引用变量的类型被用于检查一个方法是否存在。
在运行时,Java虚拟机知道,虽然对象的类型是Animal
,但是在运行时对象引用指向一个Dog
实例。所以,调用Dog
的stinky()
方法。这就是动态多态性。
《Simple Java》是一本讲解Java面试题的书。讲解也有不少独特之处,为了面试,《简易Java》走起!
作 者: D瓜哥,https://www.diguage.com/
原文链接:https://wordpress.diguage.com/archives/123.html
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。
原文链接:https://wordpress.diguage.com/archives/123.html
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。