19

可能的重复:
多态性 vs 覆盖 vs 重载

我很想知道为什么java中 需要方法重载和覆盖?

我已经阅读了一些关于此的文章,但无法理解为什么实际上需要它?

我还在stackoverflow中访问了以下网址,但我还不清楚这个话题。

Java重载和覆盖

任何实际示例将不胜感激。

提前致谢。

4

3 回答 3

47

来自doc
Method Overloading:假设您有一个类可以使用书法来绘制各种类型的数据(字符串、整数等),并且包含用于绘制每种数据类型的方法。为每个方法使用新名称很麻烦,例如 drawString、drawInteger、drawFloat 等。在 Java 编程语言中,您可以对所有绘图方法使用相同的名称,但将不同的参数列表传递给每个方法。因此,数据绘图类可能会声明四个名为 draw 的方法,每个方法都有不同的参数列表。

public class DataArtist {
    ...
    public void draw(String s) {
        ...
    }
    public void draw(int i) {
        ...
    }
    public void draw(double f) {
        ...
    }
    public void draw(int i, double f) {
        ...
    }
}

重载的方法通过传递给方法的参数的数量和类型来区分。在代码示例中,draw(String s)draw(int i)是不同且独特的方法,因为它们需要不同的参数类型。

您不能声明多个具有相同名称和相同数量和类型的参数的方法,因为编译器无法区分它们。

编译器在区分方法时不考虑返回类型,因此即使它们具有不同的返回类型,也不能声明具有相同签名的两个方法。

在面向对象的编程中,方法覆盖是一种语言特性,它允许子类或子类提供已由其超类或父类之一提供的方法的特定实现。子类中的实现通过提供与父类中的方法具有相同名称、相同参数或签名以及相同返回类型的方法来覆盖(替换)超类中的实现。执行的方法的版本将由用于调用它的对象确定。如果使用父类的对象调用方法,则执行父类中的版本,如果使用子类的对象调用方法,则执行子类中的版本。

于 2013-01-09T05:10:01.720 回答
22

覆盖

Java 文档说:

子类中具有相同签名(名称,加上其参数的编号和类型)和返回类型作为超类中的实例方法的实例方法会覆盖超类的方法。

子类重写方法的能力允许类从行为“足够接近”的超类继承,然后根据需要修改行为。

覆盖是使用继承时可用的功能。

当从另一个类扩展的类想要使用父类的大部分功能并希望在某些情况下实现特定功能时使用它。

在这种情况下,我们可以创建与父类具有相同名称和签名的方法。这样,新方法会屏蔽父方法,默认情况下会被调用。

class Thought {
    public void message() {
        System.out.println("I feel like I am diagonally parked in a parallel universe.");
    }
}

public class Advice extends Thought {
    @Override  // @Override annotation in Java 5 is optional but helpful.
    public void message() {
        System.out.println("Warning: Dates in calendar are closer than they appear.");
    }
}

重载

Java 中的重载是创建多个同名但参数不同的方法的能力。

这样做的主要优点是代码的简洁性。

让我们采取String.valueOf方法。此方法的重载版本定义为:

static String valueOf(boolean b) 
static String valueOf(char c) 
static String valueOf(char[] data) 
static String valueOf(char[] data, int offset, int count) 
static String valueOf(double d) 
static String valueOf(float f) 
static String valueOf(int i) 
static String valueOf(long l) 
static String valueOf(Object obj) 

这意味着如果我们有任何类型的变量,我们可以使用String.valueOf(variable).

如果不允许重载,我们将拥有如下所示的方法......

static String valueOfBoolean(boolean b) 
static String valueOfChar(char c) 
static String valueOfCharArray(char[] data) 
static String valueOfCharArrayWithOffset(char[] data, int offset, int count) 
static String valueOfDouble(double d) 
static String valueOfFloat(float f) 
static String valueOfInt(int i) 
static String valueOfLong(long l) 
static String valueOfObject(Object obj) 

...这比重载的解决方案非常丑陋且难以阅读。

于 2013-01-09T05:21:09.510 回答
2

答案主要集中在interfaces 和abstract classes 的使用上。

假设您有一段代码:

abstract class testAbstract {
    int a; int b; int c;
    public String testFunction() {
        System.out.println("Override me!");
        return "default";
    }

    public void setValuesByFormula(double a, double b) {
        System.out.println("No formula set!");
    }
}

这不是打赌的例子,但假设这是为了允许用户从公式中设置ab和。c用户想创建一个新的实例:

class testClass extends testAbstract {
}

该课程testClass目前包含...什么都没有。但它扩展testAbstract,因此具有功能setValuesByFormula。但是,当用户尝试调用它时,系统会输出消息:No formula set!

用户此时必须做的是@Override原始功能。因此,新类变为:

class testClass extends testInterface {
    public void setValuesByFormula(double a, double b) {
        //A not really relevant formula goes here.
    }
}

No formula set!这会在用户创建自己的公式时停止消息。这主要有几个原因:

  1. 如果一个函数是从一个超类继承的,通常孩子会想要覆盖那个函数。但是,超类可能具有其类的默认代码。因此,如果用户希望使用自己的代码,则必须覆盖此函数。
  2. 通常,超类希望使用默认代码确保某个函数将无错误地返回。在其他情况下,默认代码也很有帮助。因此,这提供了另一种选择:如果用户不需要默认代码,他们可以覆盖它。
于 2013-01-09T05:13:32.003 回答