<h1>Java 重写(Override)与重载(Overload)</h1>
重写(Override)
重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!
重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。
重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。例如: 父类的一个方法申明了一个检查异常 IOException,但是在重写这个方法的时候不能抛出 Exception 异常,因为 Exception 是 IOException 的父类,只能抛出 IOException 的子类异常。
在面向对象原则里,重写意味着可以重写任何现有方法。实例如下:
TestDog.java 文件代码:
class Dog extends Animal{
public void move(){
System.out.println(“狗可以跑和走”);
}
}
public class TestDog{
public static void main(String args[]){
Animal a = new Animal(); // Animal 对象
Animal b = new Dog(); // Dog 对象
</span><span class="hl-identifier">a</span><span class="hl-code">.</span><span class="hl-identifier">move</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">;</span><span class="hl-comment">//</span><span class="hl-comment"> 执行 Animal 类的方法</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-identifier">b</span><span class="hl-code">.</span><span class="hl-identifier">move</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">;</span><span class="hl-comment">//</span><span class="hl-comment">执行 Dog 类的方法</span><span class="hl-comment"></span><span class="hl-code">
}
}
以上实例编译运行结果如下:
动物可以移动 狗可以跑和走
在上面的例子中可以看到,尽管b属于Animal类型,但是它运行的是Dog类的move方法。
这是由于在编译阶段,只是检查参数的引用类型。
然而在运行时,Java虚拟机(JVM)指定对象的类型并且运行该对象的方法。
因此在上面的例子中,之所以能编译成功,是因为Animal类中存在move方法,然而运行时,运行的是特定对象的方法。
思考以下例子:
TestDog.java 文件代码:
class Dog extends Animal{
public void move(){
System.out.println(“狗可以跑和走”);
}
public void bark(){
System.out.println(“狗可以吠叫”);
}
}
public class TestDog{
public static void main(String args[]){
Animal a = new Animal(); // Animal 对象
Animal b = new Dog(); // Dog 对象
</span><span class="hl-identifier">a</span><span class="hl-code">.</span><span class="hl-identifier">move</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">;</span><span class="hl-comment">//</span><span class="hl-comment"> 执行 Animal 类的方法</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-identifier">b</span><span class="hl-code">.</span><span class="hl-identifier">move</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">;</span><span class="hl-comment">//</span><span class="hl-comment">执行 Dog 类的方法</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-identifier">b</span><span class="hl-code">.</span><span class="hl-identifier">bark</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">;
}
}
以上实例编译运行结果如下:
TestDog.java:30: cannot find symbol symbol : method bark() location: class Animal b.bark(); ^
该程序将抛出一个编译错误,因为b的引用类型Animal没有bark方法。
方法的重写规则
- 参数列表必须完全与被重写方法的相同;
- 返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类(java5 及更早版本返回类型要一样,java7 及更高版本可以不同);
- 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为public,那么在子类中重写该方法就不能声明为protected。
- 父类的成员方法只能被它的子类重写。
- 声明为final的方法不能被重写。
- 声明为static的方法不能被重写,但是能够被再次声明。
<li> 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为private和final的方法。</li> <li> 子类和父类不在同一个包中,那么子类只能够重写父类的声明为public和protected的非final方法。</li> <li> 重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。</li> <li> 构造方法不能被重写。</li> <li>如果不能继承一个方法,则不能重写这个方法。</li>
Super关键字的使用
当需要在子类中调用父类的被重写方法时,要使用super关键字。
TestDog.java 文件代码:
class Dog extends Animal{
public void move(){
super.move(); // 应用super类的方法
System.out.println(“狗可以跑和走”);
}
}
public class TestDog{
public static void main(String args[]){
</span><span class="hl-identifier">Animal</span><span class="hl-code"> </span><span class="hl-identifier">b</span><span class="hl-code"> = </span><span class="hl-reserved">new</span><span class="hl-code"> </span><span class="hl-identifier">Dog</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-comment">//</span><span class="hl-comment"> Dog 对象</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-identifier">b</span><span class="hl-code">.</span><span class="hl-identifier">move</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-comment">//</span><span class="hl-comment">执行 Dog类的方法</span><span class="hl-comment"></span><span class="hl-code">
}
}
以上实例编译运行结果如下:
动物可以移动 狗可以跑和走
重载(Overload)
重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
最常用的地方就是构造器的重载。
重载规则:
- 被重载的方法必须改变参数列表(参数个数或类型不一样);
- 被重载的方法可以改变返回类型;
- 被重载的方法可以改变访问修饰符;
- 被重载的方法可以声明新的或更广的检查异常;
- 方法能够在同一个类中或者在一个子类中被重载。
- 无法以返回值类型作为重载函数的区分标准。
实例
Overloading.java 文件代码:
</span><span class="hl-reserved">public</span><span class="hl-code"> </span><span class="hl-types">void</span><span class="hl-code"> </span><span class="hl-identifier">test</span><span class="hl-brackets">(</span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">a</span><span class="hl-brackets">)</span><span class="hl-brackets">{</span><span class="hl-code">
</span><span class="hl-identifier">System</span><span class="hl-code">.</span><span class="hl-identifier">out</span><span class="hl-code">.</span><span class="hl-identifier">println</span><span class="hl-brackets">(</span><span class="hl-quotes">"</span><span class="hl-string">test2</span><span class="hl-quotes">"</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-brackets">}</span><span class="hl-code">
</span><span class="hl-comment">//</span><span class="hl-comment">以下两个参数类型顺序不同</span><span class="hl-comment"></span><span class="hl-code">
</span><span class="hl-reserved">public</span><span class="hl-code"> </span><span class="hl-identifier">String</span><span class="hl-code"> </span><span class="hl-identifier">test</span><span class="hl-brackets">(</span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">a</span><span class="hl-code">,</span><span class="hl-identifier">String</span><span class="hl-code"> </span><span class="hl-identifier">s</span><span class="hl-brackets">)</span><span class="hl-brackets">{</span><span class="hl-code">
</span><span class="hl-identifier">System</span><span class="hl-code">.</span><span class="hl-identifier">out</span><span class="hl-code">.</span><span class="hl-identifier">println</span><span class="hl-brackets">(</span><span class="hl-quotes">"</span><span class="hl-string">test3</span><span class="hl-quotes">"</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-quotes">"</span><span class="hl-string">returntest3</span><span class="hl-quotes">"</span><span class="hl-code">;
</span><span class="hl-brackets">}</span><span class="hl-code">
</span><span class="hl-reserved">public</span><span class="hl-code"> </span><span class="hl-identifier">String</span><span class="hl-code"> </span><span class="hl-identifier">test</span><span class="hl-brackets">(</span><span class="hl-identifier">String</span><span class="hl-code"> </span><span class="hl-identifier">s</span><span class="hl-code">,</span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">a</span><span class="hl-brackets">)</span><span class="hl-brackets">{</span><span class="hl-code">
</span><span class="hl-identifier">System</span><span class="hl-code">.</span><span class="hl-identifier">out</span><span class="hl-code">.</span><span class="hl-identifier">println</span><span class="hl-brackets">(</span><span class="hl-quotes">"</span><span class="hl-string">test4</span><span class="hl-quotes">"</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-quotes">"</span><span class="hl-string">returntest4</span><span class="hl-quotes">"</span><span class="hl-code">;
</span><span class="hl-brackets">}</span><span class="hl-code">
</span><span class="hl-reserved">public</span><span class="hl-code"> </span><span class="hl-types">static</span><span class="hl-code"> </span><span class="hl-types">void</span><span class="hl-code"> </span><span class="hl-identifier">main</span><span class="hl-brackets">(</span><span class="hl-identifier">String</span><span class="hl-brackets">[</span><span class="hl-brackets">]</span><span class="hl-code"> </span><span class="hl-identifier">args</span><span class="hl-brackets">)</span><span class="hl-brackets">{</span><span class="hl-code">
</span><span class="hl-identifier">Overloading</span><span class="hl-code"> </span><span class="hl-identifier">o</span><span class="hl-code"> = </span><span class="hl-reserved">new</span><span class="hl-code"> </span><span class="hl-identifier">Overloading</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-identifier">System</span><span class="hl-code">.</span><span class="hl-identifier">out</span><span class="hl-code">.</span><span class="hl-identifier">println</span><span class="hl-brackets">(</span><span class="hl-identifier">o</span><span class="hl-code">.</span><span class="hl-identifier">test</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-identifier">o</span><span class="hl-code">.</span><span class="hl-identifier">test</span><span class="hl-brackets">(</span><span class="hl-number">1</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-identifier">System</span><span class="hl-code">.</span><span class="hl-identifier">out</span><span class="hl-code">.</span><span class="hl-identifier">println</span><span class="hl-brackets">(</span><span class="hl-identifier">o</span><span class="hl-code">.</span><span class="hl-identifier">test</span><span class="hl-brackets">(</span><span class="hl-number">1</span><span class="hl-code">,</span><span class="hl-quotes">"</span><span class="hl-string">test3</span><span class="hl-quotes">"</span><span class="hl-brackets">)</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-identifier">System</span><span class="hl-code">.</span><span class="hl-identifier">out</span><span class="hl-code">.</span><span class="hl-identifier">println</span><span class="hl-brackets">(</span><span class="hl-identifier">o</span><span class="hl-code">.</span><span class="hl-identifier">test</span><span class="hl-brackets">(</span><span class="hl-quotes">"</span><span class="hl-string">test4</span><span class="hl-quotes">"</span><span class="hl-code">,</span><span class="hl-number">1</span><span class="hl-brackets">)</span><span class="hl-brackets">)</span><span class="hl-code">;
</span><span class="hl-brackets">}</span><span class="hl-code">
}
重写与重载之间的区别
区别点 | 重载方法 | 重写方法 |
---|---|---|
参数列表 | 必须修改 | 一定不能修改 |
返回类型 | 可以修改 | 一定不能修改 |
异常 | 可以修改 | 可以减少或删除,一定不能抛出新的或者更广的异常 |
访问 | 可以修改 | 一定不能做更严格的限制(可以降低限制) |
总结
方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。
- (1)方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)。
- (2)方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding)。
- (3)方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
</div>
</div>
<div class="previous-next-links">
<div class="previous-design-link"><a href="http://www.runoob.com/java/java-inheritance.html"><i style="font-size:16px;" class="fa fa-arrow-left" aria-hidden="true"></i></a> <a href="http://www.runoob.com/java/java-inheritance.html" rel="prev" title="Java 继承">Java 继承</a> </div>
<div class="next-design-link"><a href="http://www.runoob.com/java/java-polymorphism.html" rel="next" title="Java 多态">Java 多态</a> <a href="http://www.runoob.com/java/java-polymorphism.html"><i style="font-size:16px;" class="fa fa-arrow-right" aria-hidden="true"></i></a></div>
</div>
<!-- 笔记列表 -->
<style>
.wrapper {
/*text-transform: uppercase; /
background: #ececec;
color: #555;
cursor: help;
font-family: “Gill Sans”, Impact, sans-serif;
font-size: 20px;
position: relative;
text-align: center;
width: 200px;
-webkit-transform: translateZ(0); / webkit flicker fix /
-webkit-font-smoothing: antialiased; / webkit text rendering fix */
}
.wrapper .tooltip {
white-space: nowrap;
font-size: 14px;
text-align: left;
background: #96b97d;
bottom: 100%;
color: #fff;
display: block;
left: -25px;
margin-bottom: 15px;
opacity: 0;
padding: 14px;
pointer-events: none;
position: absolute;
-webkit-transform: translateY(10px);
-moz-transform: translateY(10px);
-ms-transform: translateY(10px);
-o-transform: translateY(10px);
transform: translateY(10px);
-webkit-transition: all .25s ease-out;
-moz-transition: all .25s ease-out;
-ms-transition: all .25s ease-out;
-o-transition: all .25s ease-out;
transition: all .25s ease-out;
-webkit-box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.28);
-moz-box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.28);
-ms-box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.28);
-o-box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.28);
box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.28);
}
.tooltip a {
color:#fff;
}
/* This bridges the gap so you can mouse into the tooltip without it disappearing */
.wrapper .tooltip:before {
bottom: -20px;
content: " ";
display: block;
height: 20px;
left: 0;
position: absolute;
width: 100%;
}
/* CSS Triangles - see Trevor’s post */
.wrapper .tooltip:after {
border-left: solid transparent 10px;
border-right: solid transparent 10px;
border-top: solid #96b97d 10px;
bottom: -10px;
content: " ";
height: 0;
left: 20%;
margin-left: -13px;
position: absolute;
width: 0;
}
.wrapper .tooltip1 {
margin-left: 50px;
padding-top: 0px;
}
.wrapper:hover .tooltip {
opacity: 1;
pointer-events: auto;
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
-ms-transform: translateY(0px);
-o-transform: translateY(0px);
transform: translateY(0px);
}
/* IE can just show/hide with no transition */
.lte8 .wrapper .tooltip {
display: none;
}
.lte8 .wrapper:hover .tooltip {
display: block;
}
9 篇笔记 写笔记
}
输出结果:
你输入了整数:1
你输入了浮点数:3.1415
你输入了字符串:我是栗子
- #7
九刃
528***187@qq.com
补充:父类申明变量指向子类实例,该父类变量不能调用父类不存在的变量和方法,否则会编译错误
class Animal{ public void move(){ System.out.println("动物可以移动"); } }
class Dog extends Animal{
public int age;
public void move(){
age = 10;
System.out.println(“狗可以跑和走”);
}
public void bark(){
System.out.println(“狗可以吠叫”);
}
}public class TestOverride{
public static void main(String args[]){
Animal a = new Animal(); // Animal 对象
Animal b = new Dog(); // Dog 对象a</span><span class="pun">.</span><span class="pln">move</span><span class="pun">();</span><span class="com">// 执行 Animal 类的方法</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">move</span><span class="pun">();</span><span class="com">//执行 Dog 类的方法</span><span class="pln"> </span><span class="com">// b.age;//去掉前注释符号,会编译错误</span><span class="pln"> </span><span class="com">// b.bark();//去掉前注释符号,会编译错误</span><span class="pln">
}
}- #6
luzhe610
sci***n@qq.com
重载与重写的简明理解:
- 重载反映的是"随机应变". 同样一项功能, 根据数据类型的不同, 采用不同的处理方式. 比如, 同样是吃饭, 去高档餐厅吃西餐, 你会西装革履, 但是去吃火锅, 穿便装就比较合适.
- 重写反映的是"父子差异". 你"继承"了父亲吃火锅的爱好, 但是吃同一份鸳鸯锅(注意, 数据类型相同) , 你喜欢涮红汤, 你父亲喜欢涮清汤.
- #5
TJ
133***99286@163.com
关于重载函数参数列表变化的可能性:
/** * @author tangjia * @date 2017年10月29日 下午4:29:06 * @version 1.0 * @since jdk 1.8.0_65 * 类说明:测试重载函数 */ public class Main { public static void main(String[] args) { int age = 10; String name = "ii"; handle(age); handle(name); handle(name,age); handle(age,name); } public static void handle(int age) { System.out.println(age); } public static void handle(String name) { System.out.println(name); } public static void handle(int age,String name) { System.out.println("the age of "+name+" is "+age); } public static void handle(String name, int age) { System.out.println("the age of "+name+" is "+age); } }
- 1.参数类型变化,如参数从int 转变为String 类型
- 2.参数个数变化,如参数个数从一个转变为两个
- 3.参数顺序变化,如从handle(int age, String name)转变为handle(String name,int age)
- 4.函数返回值可变可不变
- #3
Anchorin
Anc***in@foxmail.com
父类变量指向子类实例时可以使用强制类型转换访问父类没有的子类成员。
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
People a=new People();
People b=new Up(6);
a.bark();
b.bark();
System.out.println(((Up)b).level); // 强制类型转换
}
}class People{
public void bark(){
System.out.println(“Hello!”);
}
}class Up extends People{
public int level;
public Up(int lv){
level=lv;
}public void bark(){
System.out.println(“鸽了鸽了,不播了”);
}
}实例输出结果为:
Hello! 鸽了鸽了,不播了 6
- #2
独孤尚良
yut***hanlin@qq.com
重写和重载的区别,以红烧为例。
红烧是一种做菜方法,可用来被比作 java 的方法。食材可以被比作为参数。厨师师徒可被比作为父子类。
方法的继承可以看做红烧这个做菜方法厨师老师传给厨师徒弟。
同样的红烧鱼,厨师老师的红烧方法传给厨师徒弟后,厨师徒弟在红烧方法上做了改动,这是红烧方法的重写,就相当于 java 的方法重写。
重写代码类似如下:
class Ct{ void hongshao(int a){ System.out.println("这是厨师老师的红烧int的方法"); } } class Cs extends Ct{ void hongshao(int a) { System.out.println("这是厨师徒弟的红烧int的方法"); } }
我找厨师徒弟做菜,我说要红烧,我给他鱼他就做的是红烧鱼,我给他排骨他就做的是红烧排骨,我给他鱼和排骨他就做的是红烧鱼和排骨。食材的不同就相当于 java 方法的参数不同,这个是重载。
重载代码类似如下:
class Cs extends Ct{ void hongshao(int a) { System.out.println("这是厨师徒弟的红烧int的方法"); } void hongshao(float b) { System.out.println("这是厨师徒弟红烧float的方法"); } void hongshao(int a,float b) { System.out.println("这是厨师徒弟红烧int和float的方法"); } }
- #1
韶华轻负
jia***ihua77@163.com
对于重写和重载的一些浅薄认识。
重写:我从我的父亲继承了一个中餐馆,但是我觉得中餐馆不够,于是我又在中餐馆的基础上加了个西餐馆。
class Chinese{ public void style(){ System.out.printhl("赣菜中餐馆"); } } class western extends Chinese{ public void style(){ System.out.printhl("西餐厅"); } }
餐厅还是那个餐厅,只是我继承过来加入了自己独有的方法。
重载:本来我只开了一个赣菜馆,但是我觉得菜系不够,于是我又增加了川菜、粤菜....
public class Chinese{ public void style(){ System.out.printhl("赣菜中餐馆"); } public void style(int a){ System.out.printhl("a川菜中餐馆"); } public void style(String b){ System.out.printhl("b粤菜中餐馆"); } }
做饭的方法并没有改变,只是参数不同,返回的值也不一样。
horse
guo***gren1107@163.com
重载就是同样的一个方法能够根据输入数据的不同,做出不同的处理
重写就是当子类继承自父类的相同方法,输入数据一样,但要做出有别于父类的响应时,你就要覆盖父类方法
horse
guo***gren1107@163.com
我一点都不方
274***2310@qq.com
重载是同样的一个方法写多次变量修饰符不一样,当调用方法时,会自动判断给入数的类型,选取其中符合的方法。