一、重写(Override)

  • 重写是子类对父类允许访问的方法的实现过程进行重新编写,返回值和形参都不能改变。即外壳不变,核心重写!重写的优势在于子类可以根据需要,定义适合自己的特定行为。

注意:

  • 重写方法不能抛出新的检查异常或者比被重写的方法申明更加宽泛的异常。例如:父类的某个方法申明了一个检查异常IOException,而在重写此方法时不能抛出Exception异常,因为Exception是IOException 的父类,只能抛出IOException的子类异常。
  • 在面向对象原则里,重写意味着可以重写任何现有方法。

二、重写实例1

class Animal{  // 定义父类Animal
   public void move(){  // 定义父类Animal中的方法move
      System.out.println("动物可以移动");
   }
}
class Dog extends Animal{  // 定义子类Dog‘继承’父类Animal
   public void move(){  // ‘重写’父类Animal中的方法move
      System.out.println("狗可以跑和走");
   }
}
public class TestDog{
   public static void main(String args[]){
      Animal animal = new Animal();  // Animal对象
      Animal dog = new Dog();  // Dog对象 
      animal.move();  // 执行Animal类的方法move,输出“动物可以移动”
      dog.move();  // 执行Dog类的方法move,输出“狗可以跑和走”
   }
}

三、重写实例2

class Animal{  // 定义父类Animal
   public void move(){  // 定义父类Animal中的方法move
      System.out.println("动物可以移动");
   }
}
class Dog extends Animal{  // 定义子类Dog‘继承’父类Animal
   public void move(){  // ‘重写’父类Animal中的方法move
      System.out.println("狗可以跑和走");
   }
   public void bark(){  // 定义子类Dog中的方法bark
      System.out.println("狗可以吠叫");
   }
}
public class TestDog{
   public static void main(String args[]){
      Animal animal = new Animal();  // Animal对象
      Animal dog = new Dog();  // Dog对象 
      animal.move();  // 执行Animal类的方法move,输出“动物可以移动”
      dog.move();  // 执行Dog类的方法move,输出“狗可以跑和走”
      dog.bark();  // 执行Dog类的方法bark,!编译错误!(dog的引用类型Animal无bark方法)
   }
}

四、重写规则

  • 参数列表必须完全与被重写方法相同。
  • 返回类型与被重写方法的返回类型可以不同,但是必须是父类返回值的派生类。
  • 访问权限不能比父类中被重写方法的访问权限更低。
  • 父类的成员方法只能被它的子类重写。
  • 声明为final的方法不能被重写。
  • 声明为static的方法不能被重写,但是能够被再次声明。
  • 子类和父类在同一包中,那么子类可以重写父类所有方法,除了声明为private和final的方法。
  • 子类和父类不在同一包中,那么子类只能重写父类声明为public和protected的非final方法。
  • 无论被重写方法是否抛出异常,重写方法能够抛出任何非强制异常。但是,重写方法不能抛出新的强制性异常或者比被重写方法声明的更广泛的强制性异常,反之则可以。
  • 构造方法不能被重写。
  • 如果不能继承一个方法,则不能重写这个方法。

五、关键字Super

  • 目的:需要在子类中调用父类的被重写方法。
    class Animal{  // 定义父类Animal
     public void move(){  // 定义父类Animal的方法move
        System.out.println("动物可以移动");
     }
    }
    class Dog extends Animal{  // 定义子类Dog‘继承’父类Animal
     public void move(){  // ‘重写’父类Animal的方法move
        super.move(); // 调用父类Animal的方法move
        System.out.println("狗可以跑和走");
     }
    }
    public class TestDog{
     public static void main(String args[]){
        Animal dog = new Dog();  // Dog对象
        dog.move();  // 执行Dog类的方法move,输出“动物可以移动”,“狗可以跑和走”
     }
    }

六、重载(Overload)

  • 重载是指一个类中,方法名字相同而参数不同,返回类型可以相同也可以不同。每一个重载方法(或者构造函数)都必须有一个独一无二的参数类型列表。最常用于构造器的重载。

七、重载规则

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

八、重载实例

public class Overloading {
    public int test(){  // 定义第一个test方法,无参数
        System.out.println("test1");
        return 1;  // 返回类型是整型
    }
    public void test(int a){  // ‘重载’第二个test方法,包含一个整型参数,无返回
        System.out.println("test2");
    }   
    public String test(int a, String s){  // ‘重载’第三个test方法,参数顺序是整型、字符串型
        System.out.println("test3");
        return "returntest3";  // 返回类型是字符串型
    }   
    public String test(String s, int a){  // ‘重载’第四个test方法,参数顺序是字符串型、整型
        System.out.println("test4");
        return "returntest4";  // 返回类型是字符串型
    }   
    public static void main(String[] args){
        Overloading overloading = new Overloading();
        System.out.println(overloading.test());  // 调用第一个test方法,输出“test1”,“1”
        overloading.test(1);  // 调用第二个test方法,输出“test2”
        System.out.println(overloading.test(1,"test3"));  // 调用第三个test方法,输出“test3”,“returntest3”
        System.out.println(overloading.test("test4",1));  // 调用第四个test方法,输出“test4”,“returntest4”
    }
}

九、重写与重载的区别

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

十、总结

  • 重写是在子类中存在方法与父类方法的名字相同,且参数的个数与类型一样,返回值相同的方法。
  • 重载是一个类中定义了多个方法名相同,而参数的数量不同或数量相同而类型和次序不同。
  • 重写(Overriding)和重载(Overloading)是Java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载则是一个类的多态性具体表现形式。