为什么java中需要方法重载和覆盖?

时间:2013-01-09 04:59:03

标签: java

  

可能重复:
  Polymorphism vs Overriding vs Overloading

我很难知道为什么方法重载和覆盖所需的在java中?

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

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

Java overloading and overriding

任何实际的例子将不胜感激。

提前致谢。

3 个答案:

答案 0 :(得分:39)

来自doc
方法重载:假设您有一个类可以使用书法来绘制各种类型的数据(字符串,整数等),并且包含绘制每种数据类型的方法。为每个方法使用新名称很麻烦 - 例如,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)是不同且唯一的方法,因为它们需要不同的参数类型。

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

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

在面向对象编程中,

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

答案 1 :(得分:19)

<强>重写

Java Docs说:

  

具有相同签名的子类中的实例方法(name,plus   它的参数的数量和类型)和返回类型   超类中的instance方法会覆盖超类的方法。

     

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

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

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

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

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.");
    }
}

<强> Overloading

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)获取它的String表示。

如果不允许超载,我们的方法看起来像这样......

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) 

......与重载的解决方案相比,它非常丑陋且难以阅读。

答案 2 :(得分:2)

答案主要围绕interfaceabstract class es的使用。

假设您有一段代码:

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!");
    }
}

这不是赌注的例子,但我们可以说这是为了让用户可以从公式中设置abc。用户想要创建一个新的实例:

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. 通常,超类希望使用默认代码确保某个函数将返回而不会出现错误。还有其他默认代码有用的实例。因此,这提供了另一种选择:如果用户不需要默认代码,他们可以覆盖它。