菜鸟教程 -- 学的不仅是技术,更是梦想!

Java 教程
(追記) (追記ここまで)

Java 重写(Override)与重载(Overload)


重写(Override)

重写(Override)是指子类定义了一个与其父类中具有相同名称、参数列表和返回类型的方法,并且子类方法的实现覆盖了父类方法的实现。 即外壳不变,核心重写!

重写的好处在于子类可以根据需要,定义特定于自己的行为。也就是说子类能够根据需要实现父类的方法。这样,在使用子类对象调用该方法时,将执行子类中的方法而不是父类中的方法。

重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。例如: 父类的一个方法申明了一个检查异常 IOException,但是在重写这个方法的时候不能抛出 Exception 异常,因为 Exception 是 IOException 的父类,抛出 IOException 异常或者 IOException 的子类异常。

在面向对象原则里,重写意味着可以重写任何现有方法。实例如下:

TestDog.java 文件代码:

classAnimal{publicvoidmove(){System.out.println("动物可以移动"); }}classDogextendsAnimal{publicvoidmove(){System.out.println("狗可以跑和走"); }}publicclassTestDog{publicstaticvoidmain(Stringargs[]){Animala = newAnimal(); // Animal 对象Animalb = newDog(); // Dog 对象a.move();// 执行 Animal 类的方法b.move();//执行 Dog 类的方法}}

以上实例编译运行结果如下:

动物可以移动
狗可以跑和走

在上面的例子中可以看到,尽管 b 属于 Animal 类型,但是它运行的是 Dog 类的 move方法。

这是由于在编译阶段,只是检查参数的引用类型。

然而在运行时,Java 虚拟机(JVM)指定对象的类型并且运行该对象的方法。

因此在上面的例子中,之所以能编译成功,是因为 Animal 类中存在 move 方法,然而运行时,运行的是特定对象的方法。

思考以下例子:

TestDog.java 文件代码:

classAnimal{publicvoidmove(){System.out.println("动物可以移动"); }}classDogextendsAnimal{publicvoidmove(){System.out.println("狗可以跑和走"); }publicvoidbark(){System.out.println("狗可以吠叫"); }}publicclassTestDog{publicstaticvoidmain(Stringargs[]){Animala = newAnimal(); // Animal 对象Animalb = newDog(); // Dog 对象a.move();// 执行 Animal 类的方法b.move();//执行 Dog 类的方法b.bark(); }}

以上实例编译运行结果如下:

TestDog.java:30: cannot find symbol
symbol : method bark()
location: class Animal
 b.bark();
 ^

该程序将抛出一个编译错误,因为b的引用类型Animal没有bark方法。


方法的重写规则

  • 参数列表与被重写方法的参数列表必须完全相同。

  • 返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类(java5 及更早版本返回类型要一样,java7 及更高版本可以不同)。

  • 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected。

  • 父类的成员方法只能被它的子类重写。

  • 声明为 final 的方法不能被重写。

  • 声明为 static 的方法不能被重写,但是能够被再次声明。

  • 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。

  • 子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。

  • 重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。

  • 构造方法不能被重写。

  • 如果不能继承一个类,则不能重写该类的方法。


Super 关键字的使用

当需要在子类中调用父类的被重写方法时,要使用 super 关键字。

TestDog.java 文件代码:

classAnimal{publicvoidmove(){System.out.println("动物可以移动"); }}classDogextendsAnimal{publicvoidmove(){super.move(); // 应用super类的方法System.out.println("狗可以跑和走"); }}publicclassTestDog{publicstaticvoidmain(Stringargs[]){Animalb = newDog(); // Dog 对象b.move(); //执行 Dog类的方法}}

以上实例编译运行结果如下:

动物可以移动
狗可以跑和走

重载(Overload)

重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。

每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。

最常用的地方就是构造器的重载。

重载规则:

  • 被重载的方法必须改变参数列表(参数个数或类型不一样);
  • 被重载的方法可以改变返回类型;
  • 被重载的方法可以改变访问修饰符;
  • 被重载的方法可以声明新的或更广的检查异常;
  • 方法能够在同一个类中或者在一个子类中被重载。
  • 无法以返回值类型作为重载函数的区分标准。

实例

Overloading.java 文件代码:

publicclassOverloading{publicinttest(){System.out.println("test1"); return1; }publicvoidtest(inta){System.out.println("test2"); }//以下两个参数类型顺序不同publicStringtest(inta,Strings){System.out.println("test3"); return"returntest3"; }publicStringtest(Strings,inta){System.out.println("test4"); return"returntest4"; }publicstaticvoidmain(String[]args){Overloadingo = newOverloading(); System.out.println(o.test()); o.test(1); System.out.println(o.test(1,"test3")); System.out.println(o.test("test4",1)); }}

重写与重载之间的区别

区别点 重载方法 重写方法
参数列表 必须修改 一定不能修改
返回类型 可以修改 一定不能修改
异常 可以修改 可以减少或删除,一定不能抛出新的或者更广的异常
访问 可以修改 一定不能做更严格的限制(可以降低限制)

总结

方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。

  • (1)方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)。
  • (2)方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding)。
  • (3)方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
AI 思考中...

11 篇笔记 写笔记

  1. #0

    horse

    guo***[email protected]

    300

    重载就是同样的一个方法能够根据输入数据的不同,做出不同的处理

    重写就是当子类继承自父类的相同方法,输入数据一样,但要做出有别于父类的响应时,你就要覆盖父类方法

    horse

    guo***[email protected]

    9年前 (2017年05月12日)
  2. #0

    我一点都不方

    274***[email protected]

    76

    重载是同样的一个方法写多次变量修饰符不一样,当调用方法时,会自动判断给入数的类型,选取其中符合的方法。

    public class Overloading {
     private static int i = 1;
     private static double l = 3.1415;
     private static String k = "我是栗子";
     //参数类型不同
     public void test(int a){
     System.out.println("你输入了整数:"+a);
     } 
     
     public void test(double a){
     System.out.println("你输入了浮点数:"+a);
     } 
     
     public void test(String a){
     System.out.println("你输入了字符串:"+a);
     } 
     
     public static void main(String[] args){
     Overloading lizi = new Overloading();
     lizi.test(i);
     lizi.test(l);
     lizi.test(k);
     }
    }

    输出结果:

    你输入了整数:1
    你输入了浮点数:3.1415
    你输入了字符串:我是栗子

    我一点都不方

    274***[email protected]

    9年前 (2017年06月04日)
  3. #0

    九刃

    528***[email protected]

    45

    补充:父类申明变量指向子类实例,该父类变量不能调用父类不存在的变量和方法,否则会编译错误

    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.move();// 执行 Animal 类的方法
     b.move();//执行 Dog 类的方法
     // b.age;//去掉前注释符号,会编译错误
     // b.bark();//去掉前注释符号,会编译错误
     }
    }

    九刃

    528***[email protected]

    9年前 (2017年06月27日)
  4. #0

    luzhe610

    sci***[email protected]

    107

    重载与重写的简明理解:

    • 重载反映的是"随机应变". 同样一项功能, 根据数据类型的不同, 采用不同的处理方式. 比如, 同样是吃饭, 去高档餐厅吃西餐, 你会西装革履, 但是去吃火锅, 穿便装就比较合适.
    • 重写反映的是"父子差异". 你"继承"了父亲吃火锅的爱好, 但是吃同一份鸳鸯锅(注意, 数据类型相同) , 你喜欢涮红汤, 你父亲喜欢涮清汤.

    luzhe610

    sci***[email protected]

    9年前 (2017年09月18日)
  5. #0
    21

    关于重载函数参数列表变化的可能性:

    /**
     * @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.函数返回值可变可不变
    9年前 (2017年10月29日)
  6. #0

    Xander663

    xan***[email protected]

    17

    自定义的类重载比较函数的方法:

    public class Match implements Comparable{
     public int compareTo(Object o) {
     Match tgt = (Match)o; 
     return ( this.len < tgt.len ? -1 : ( this.len == tgt.len ? 0 : 1));
     }
    }

    Xander663

    xan***[email protected]

    8年前 (2018年07月15日)
  7. #0

    Anchorin

    Anc***[email protected]

    26

    父类变量指向子类实例时可以使用强制类型转换访问父类没有的子类成员。

    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

    Anchorin

    Anc***[email protected]

    8年前 (2018年08月11日)
  8. #0

    独孤尚良

    yut***[email protected]

    34

    重写和重载的区别,以红烧为例。

    红烧是一种做菜方法,可用来被比作 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的方法");
     }
    }

    独孤尚良

    yut***[email protected]

    7年前 (2019年03月04日)
  9. #0

    韶华轻负

    jia***[email protected]

    21

    对于重写和重载的一些浅薄认识。

    重写:我从我的父亲继承了一个中餐馆,但是我觉得中餐馆不够,于是我又在中餐馆的基础上加了个西餐馆。

    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粤菜中餐馆");
     }
    }

    做饭的方法并没有改变,只是参数不同,返回的值也不一样。

    韶华轻负

    jia***[email protected]

    7年前 (2019年04月11日)
  10. #0

    alittlemc

    ali***[email protected]

    11

    重载:同名方法通过传入的参数不同(如类型、个数、排序方式)而区分不同方法\函数,与返回值无关

    对象:类内的方法之间

    例子:void a();void a(int i);int a(String str)等等,关键在传入的参数

    class A{
     void a(){
     System.out.printhl("a()");
     }
     int a(){//这样是不合法,因为返回值类型不同不能区分不同的方法
     System.out.printhl("a()");
     }
     void a(int i){//void a()
     System.out.printhl("a("+i+")");
     }
    }
    

    重写:在子类中编写与父类 返回值类型相同的同名方法 ,这样原来的父类方法就会被隐藏掉,可以使用super.方法名() 调用

    对象:父类和子类之间

    class A{
     void a(){
     System.out.printhl("a()");
     }
    }
    class B extends A{
     /*int a(){//返回值与父类的void不同,报错
     return 0;
     }*/
     
     void a(int a){//就算是可以有不同的传入
     System.out.printhl("a"+i);
     }
    }
    

    可能有错误和不足,仅供参考

    alittlemc

    ali***[email protected]

    7年前 (2019年10月08日)
  11. #0

    aojiaodexiaoyanga

    259***[email protected]

    15

    继承:我有一钱包,钱包里面有一张农行卡,有1000元现金,小明找我借钱包,我把钱包给他,他可以用里面所有的东西。

    重写和重载:(取钱为例)

    重写:小明从我的农行卡中取出100,而我本来要取1000。

    重载:去相同的钱,我选择农业银行,而小明却跑去隔壁的建设银行取钱

    aojiaodexiaoyanga

    259***[email protected]

    6年前 (2020年03月19日)

点我分享笔记

  • 昵称 (必填)
  • 邮箱 (必填)
  • 引用地址

AltStyle によって変換されたページ (->オリジナル) /