总结重写和重载区别

本文深入探讨Java中方法重写与重载的区别,包括规则、实例及代码解析,帮助开发者理解如何正确实现多态性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

重写方法的规则如下:


1. 参数列表:必须与被重写方法的参数列表完全匹配。 
2. 返回类型:必须与超类中被重写的方法中声明的返回类型或子类型完全相同 
3. 访问级别:一定不能比被重写方法强,可以比被重写方法的弱。 
4. 非检查异常:重写方法可以抛出任何非检查的异常,无论被重写方法是否声明了该异常。 
5. 检查异常:重写方法一定不能抛出新的检查异常,或比被重写方法声明的检查异常更广的检查异常 
6. 不能重写标志为final,static的方法 

重载方法的规则: 
1. 参数列表:被重载的方法必须改变参数列表。 
2. 返回类型:可以改变返回类型。 
3. 修饰符:可以改变修饰符 
4. 异常:可以声明新的或者更广泛的异常。

 

  1. class Animal {   
  2.     public void eat(){   
  3.     }   
  4. }  

以下列出对于Animal的eat方法各种重写重载实例,根据以上列出的规则,判断其是否合法(以下的方法都属于Animal的子类Horse的方法):
1. private void eat(){}  不能通过编译,非法重写,访问修饰符限制性变强;不属于重载,因为参数列表没有发生改变
2. public void eat() throw RuntimeException{}  能通过编译,属于重写,重写方法可以抛出任何非检查异常。
3. public void eat() throw IOException{}  不能通过编译,非法重写,重写方法一定不能抛出新的检查异常,或比被重写方法声明的检查异常更广的检查异常;不属于重载,参数列表必须发生变化才属于重载
4. public void eat(String food){}  能通过编译,不是重写;合法重载,因为参数列表发生改变了。
5. public String eat(){}  不能通过编译,不是重写,因为其返回类型;不是重载,因为参数列表没有发生改变。
6. public String eat(int n){} 可以通过编译,不是重写;是重载,首先参数列表必须发生变化,返回类型可以发生改变。

 

对父类被重写的方法做一个变动:

 

  1. class Animal {   
  2.     public Animal eat() throws IOException{   
  3.         return null;   
  4.     }   
  5. }  

7.  public Animal eat(){return null;}  可以通过编译,合法重写,可以不抛出异常,只要不抛出新的异常或更广泛的异常就可以。
8.  public Animal eat() throws FileNotFoundException{return null;} 可以通过编译,是重写,属于子类的非检查异常。
9.  public Animal eat() throws Exception{}  不可以通过编译,非法重写,抛出了更广泛的异常。
10.  public Horse eat() {} 可以通过编译,是重写,因为返回类型可以是被重写的返回类型的子类。

 

 

1           重载(Overloading) 
(1)       方法重载是让类以统一的方式处理不同类型数据的一种手段。多个同名函数同时
存在,具有不同的参数个数/类型。重载Overloading是一个类中多态性的一种表现。
(2)       Java的方法重载,就是在类中可以创建多个方法,它们具有相同的名字,但具
有不同的参数和不同的定义。调用方法时通过传递给它们的不同参数个数和参数类型
来决定具体使用哪个方法, 这就是多态性。
(3)       重载的时候,方法名要一样,但是参数类型和个数不一样,返回值类型可以相同
也可以不相同。无法以返回型别作为重载函数的区分标准。

 

2     重写(Overriding)
(1)    父类与子类之间的多态性,对父类的函数进行重新定义。如果在子类中定义某
            
方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。在Java中,
子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不
动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。方法重写又
称方法覆盖。
(2)    若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,
则新方法将覆盖原有的方法。如需父类中原有的方法,可使用super关键字,该关键
字引用了当前类的父类。
(3)    子类函数的访问修饰权限不能少于父类的;

 

总结:重载和重写(覆盖)。 
    
方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写
Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性
的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法
被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而
言,父类中的定义如同被“屏蔽”了,而且如果子类的方法名和参数类型和个数都和
父类相同,那么子类的返回值类型必须和父类的相同;如果在一个类中定义了多个同
名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载
(Overloading)。Overloaded的方法是可以改变返回值的类型。也就是说,重载的返回
值类型可以相同也可以不同。

<think>我们正在讨论重写(Override)重载(Overload)的区别。根据用户提供的引用内容,我们可以总结如下: 1. **定义**: - **重载(Overload)**:在同一个类中,方法名相同,但参数列表(参数类型、个数、顺序)不同的方法。返回类型可以不同,但不能仅通过返回类型不同来区分重载方法。 - **重写(Override)**:发生在子类父类之间,子类重新定义父类中已有的方法。方法名、参数列表返回类型(或子类型)必须相同。 2. **发生位置**: - 重载:同一个类中。 - 重写:子类中。 3. **多态性**: - 重载:编译时多态(静态多态)。编译器在编译时根据方法签名(方法名参数列表)决定调用哪个方法。 - 重写:运行时多态(动态多态)。在运行时根据对象的实际类型(子类)来决定调用哪个方法。 4. **方法签名**: - 重载:必须改变参数列表(参数类型、个数或顺序),返回类型可以相同也可以不同,访问修饰符抛出的异常可以不同。 - 重写:方法签名(方法名参数列表)必须相同;返回类型必须相同或是父类方法返回类型的子类型;访问修饰符不能比父类更严格(即子类方法访问权限不能小于父类方法);抛出的异常不能比父类方法抛出的异常更宽泛(即子类方法抛出的异常必须是父类方法抛出异常的子类或不抛出异常)。 5. **应用场景**: - 重载:用于处理同一功能的不同参数情况,例如,一个加法方法可以重载为处理整数、浮点数等。 - 重写:用于子类需要改变父类方法的行为时,例如,动物类有`makeSound`方法,狗类重写该方法以发出狗叫。 6. **其他限制**: - 重载:不能通过返回类型来区分,因为调用时可能无法确定。 - 重写:子类方法不能抛出比父类方法更宽泛的检查异常(即不能抛出父类方法未声明的检查异常,或者更宽泛的检查异常)。非检查异常(RuntimeException)不受此限制。 下面用代码示例说明: **重载示例(在同一个类中)**: ```java public class Calculator { // 两个整数相加 public int add(int a, int b) { return a + b; } // 重载:三个整数相加 public int add(int a, int b, int c) { return a + b + c; } // 重载:两个浮点数相加 public double add(double a, double b) { return a + b; } } ``` **重写示例(子类重写父类方法)**: ```java class Animal { public void makeSound() { System.out.println("Animal makes a sound"); } } class Dog extends Animal { @Override public void makeSound() { // 重写父类方法 System.out.println("Dog barks"); } } public class Main { public static void main(String[] args) { Animal myAnimal = new Dog(); // 向上转型 myAnimal.makeSound(); // 输出"Dog barks",运行时多态 } } ``` **总结表格**: | 特性 | 重载 (Overload) | 重写 (Override) | |--------------|------------------------------------------|------------------------------------------| | **定义** | 同一类中,方法名相同,参数列表不同 | 子类重新定义父类方法 | | **位置** | 同一个类 | 子类 | | **多态性** | 编译时多态 | 运行时多态 | | **方法签名** | 必须不同(参数类型、个数、顺序) | 必须相同 | | **返回类型** | 可以不同 | 必须相同或是父类返回类型的子类型 | | **访问修饰符**| 可以不同 | 子类方法访问权限不能比父类更严格 | | **异常** | 可以不同 | 子类方法不能抛出更宽泛的检查异常 | | **作用** | 提供同一功能的不同版本(参数不同) | 改变父类方法的行为 | 通过以上对比,我们可以清晰地理解重载重写区别重载是在同一个类中多个同名方法根据参数不同而不同,重写是子类对父类方法的具体实现进行覆盖。 §§相关问题§§ 1. 为什么重载不能根据返回类型来区分? 2. 重写时如果返回类型是父类方法返回类型的子类,具体如何实现? 3. 在Java中,如何防止一个方法被重写?</think>### 重写(Override)与重载(Overload)的区别详解 #### 1. **核心定义** | **特性** | **重载 (Overload)** | **重写 (Override)** | |----------------|----------------------------------------|-----------------------------------------| | **发生位置** | 同一个类中 | 子类与父类之间 | | **方法签名** | 方法名相同,**参数列表不同** | 方法名、参数列表、返回类型**完全相同** | | **多态类型** | 编译时多态(静态绑定) | 运行时多态(动态绑定) | | **核心目的** | 处理不同类型/数量的参数 | 改变父类方法的行为 | #### 2. **技术特性对比** - **参数要求** - 重载:必须改变参数类型/数量/顺序 ```java // 重载示例:参数类型不同 void print(int a) { ... } void print(String s) { ... } // ✅ 有效重载 ``` - 重写:参数列表必须与父类完全一致 ```java class Parent { void show(int x) { ... } } class Child extends Parent { @Override void show(int x) { ... } // ✅ 有效重写(参数相同) } ``` - **返回类型** - 重载:返回类型可自由修改 ```java int calculate() { ... } // 返回int String calculate() { ... } // ❌ 编译错误!仅返回类型不同不构成重载 ``` - 重写:返回类型必须相同或是父类返回类型的**子类型**(协变返回) ```java class Animal { Animal create() { ... } } class Dog extends Animal { @Override Dog create() { ... } // ✅ 协变返回(Dog是Animal子类) } ``` - **访问权限** - 重载:访问修饰符可任意修改(public/protected/private) - 重写:子类方法访问权限**不能严于父类** ```java class Parent { protected void demo() { ... } } class Child extends Parent { @Override public void demo() { ... } // ✅ 更宽松(允许) // private void demo() { ... } // ❌ 编译错误!更严格禁止 } ``` - **异常处理** - 重载:可抛出任意异常 - 重写:**不能抛出更宽泛的检查异常** ```java class Parent { void test() throws IOException { ... } } class Child extends Parent { @Override void test() throws FileNotFoundException { ... } // ✅ 子异常 // void test() throws Exception { ... } // ❌ 更宽泛异常 } ``` #### 3. **多态机制差异** | **阶段** | **重载** | **重写** | |------------|-----------------------------------|-----------------------------------| | **编译时** | 编译器根据**参数类型**确定调用方法 | 编译器检查方法签名是否匹配父类 | | **运行时** | 无动态绑定 | JVM根据**对象实际类型**调用方法 | **示例说明**: ```java class Animal { void sound() { System.out.println("Animal sound"); } } class Dog extends Animal { @Override void sound() { System.out.println("Bark!"); } // 重写 // 重载 void sound(int volume) { System.out.println("Bark at volume: " + volume); } } public class Test { public static void main(String[] args) { Animal a = new Dog(); // 向上转型 a.sound(); // 输出"Bark!"(运行时多态) // a.sound(10); // ❌ 编译错误!Animal类无此方法 Dog d = new Dog(); d.sound(10); // ✅ 输出"Bark at volume: 10"(编译时多态) } } ``` #### 4. **设计思想差异** - **重载**:实现**横向扩展**(同一类提供多种参数处理方式) ```java class MathUtils { // 处理不同参数类型的加法 int add(int a, int b) { return a + b; } double add(double a, double b) { return a + b; } } ``` - **重写**:实现**纵向扩展**(子类定制父类行为) ```java abstract class Shape { abstract double area(); // 抽象方法 } class Circle extends Shape { @Override double area() { ... } // 实现具体计算 } ``` #### 5. **常见误区澄清** - **重载重写** - 仅方法名相同是重载的必要条件,参数不同是充分条件 - 子类中与父类**同名不同参**的方法属于重载而非重写 - **静态方法特殊规则** ```java class Parent { static void method() { ... } } class Child extends Parent { // 这是隐藏(hide)而非重写! static void method() { ... } } ``` > **核心总结**: > 重载解决**参数多样化**问题(编译时确定),重写实现**行为定制化**问题(运行时确定)。两者共同构成面向对象的多态性支柱[^1][^2][^3]。 --- ### 重载重写对比速查表 | **特性** | 重载 (Overload) | 重写 (Override) | |------------------|-------------------------|--------------------------| | 作用范围 | 同一个类 | 子类 vs 父类 | | 参数列表 | **必须不同** | **必须相同** | | 返回类型 | 可修改 | 相同或协变类型 | | 访问修饰符 | 可任意修改 | 不能更严格 | | 异常声明 | 无限制 | 不能抛出更宽泛检查异常 | | 绑定时机 | 编译时 | 运行时 | | 多态类型 | 静态多态 | 动态多态 | | 继承要求 | 不需要 | 必须存在继承关系 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值