您的位置:

Java方法重载和重写的区别

一、引言

在JAVA编程中,方法重载和重写是两个重要的概念。虽然它们看起来类似,但是它们的语法和语义都有很大的区别。简单来说,方法重载是在一个类中,有多个相同名称的方法,但参数列表不同,以实现不同的功能。而方法重写是在子类中重新定义父类中已有的方法,以实现对该方法的修改或扩展。在该文章中,我们将从多个角度详细介绍JAVA方法重载和重写的区别。

二、JAVA方法重载和重写的区别

1. JAVA重载和重写的区别

JAVA中,方法重载(Overloading)和方法重写(Overriding)常常会被混淆。尽管两者都涉及方法的命名,但实际上它们具有截然不同的含义。

方法重载产生于同一个类中,它们具有相同的函数名称,但是参数数量或类型不同。例如:

public class Calculator {
    public int add(int x, int y) {
        return x + y;
    }
    public int add(int x, int y, int z) {
        return x + y + z;
    }
}

上述代码中,我们定义了一个名为“Calculator”的类。其中有两个具有相同名称的方法“add”,但是它们具有不同的参数数量。当我们按照不同的参数数量进行方法调用时,编译器会自动选择与调用参数类型最匹配的重载方法。

方法重写,也叫覆盖,是指子类重新定义了一个在父类中已有的方法,以覆盖父类中原有的方法实现。例如:

public class Animal {
    public void move() {
        System.out.println("Animals can move");
    }
}
public class Dog extends Animal {
    public void move() {
        System.out.println("Dogs can walk and run");
    }
}

上述代码中,我们定义了一个名为“Animal”的类,其中具有一个名为“move”的方法。我们还定义了一个名为“Dog”的类,它继承自“Animal”,并且重新定义了“move”方法的实现。尽管两者具有相同的方法名称,但其语意和实现却是不同的。

2. JAVA中方法重写的实现原则

当我们重新定义一个父类中已有的方法时,必须遵循以下三条原则:

2.1)方法的名称、参数数量和类型必须与父类中要被重写的方法相同。

public class Animal {
    public void eat() {
        System.out.println("Animal is eating");
    }
}
public class Dog extends Animal {
    public void eat() { // eat 方法重新定义
        System.out.println("Dog is eating");
    }
}

上述代码中,我们重新定义了“Animal”类中的“eat”方法。子类中重写的方法名称、参数数量和类型必须与父类中的方法完全一致。

2.2)方法的访问修饰符“不能优于”父类中被重写的方法。

访问修饰符的优先级从大到小依次是:private、缺省、protected、public。如果我们在子类中尝试用一个访问修饰符“优于”它父类中的被重写方法的访问修饰符,那么编译器就会报错。

public class Animal {
    protected void sound() {
        System.out.println("Animal is making a sound");
    }
}
public class Dog extends Animal {
   public void sound() {
        System.out.println("Dog is barking"); // error: attempting to assign weaker access privileges; was protected
    }
}

上述代码中,在“Animal”类中,我们定义了一个受保护的“sound”方法。在“Dog”类中,我们试图将其访问修饰符改为“公共”,这是行不通的。因此,我们必须将其修饰符改为“protected”。

2.3)方法的返回类型必须与父类中被重写的方法“相同”或“是它的子类”。

public class Animal {
    public Object getChild() {
        return new Animal(); // 返回一个 Animal 对象
    }
}
public class Dog extends Animal {
    public Dog getChild() { // 返回一个 Dog 对象
        return new Dog();
    }
}

上述代码中,在“Animal”类中,我们定义了一个名为“getChild”的方法,它返回一个Animal对象,并且在“Dog”类中重新定义了它,使其返回一个Dog对象。由于Dog是Animal的子类,因此我们可以将其返回类型定义为Dog。这里我们仅以这种方式将其“扩展”为例,特别需要注意的是,本原素类型并不是一个子类,所以我们不能将其返回类型定义为原来方法的本原素类型。

3. JAVA中方法重载和重写的区别

3.1)方法重载和方法重写的区别

方法重载和方法重写最大的区别是,方法重载发生在同一类中,而方法重写发生在子类和父类之间。此外,方法重载是为了实现“多样”的操作,而方法重写是为了实现“多态”的操作。

3.2)参数的不同

方法重载是指同一个类中定义多个名称相同但形参不同的方法,形参包括形参类型、形参个数和形参顺序。

public class Calculator {
    public int add(int x, int y) {
        return x + y;
    }
    public int add(int x, int y, int z) {
        return x + y + z;
    }
}

上述代码中,我们定义了两个名称相同的方法,但参数列表不同。这样,我们就可以在方法调用时,根据不同的参数调用不同的方法。

方法重写,是指子类定义一个与父类同名、同参数、同返回类型的方法,来覆盖父类的方法。

public class Animal {
    public void move() {
        System.out.println("Animals can move");
    }
}
public class Dog extends Animal {
    public void move() {
        System.out.println("Dogs can walk and run");
    }
}

上述代码中,我们在子类“Dog”中重新定义了父类“Animal”的“move”方法。最终的行为结果是,当我们使用“Dog”对象调用“move”方法时,将会运行子类中定义的方法而不是父类中定义的方法。

3.3)返回类型的不同

在方法重载中,方法必须具有相同的方法名称和不同的参数列表,但返回类型可以是任意类型,包括基础类型和对象类型。

而在方法重写中,方法必须具有相同的方法名称和参数列表,并且返回类型必须“相同”或是“子类”。这是因为返回类型涉及到继承的概念,我们必须确保方法返回的类型是合法的,即子类可以扩展给定实例(父类)的语意。如果返回类型是不同的,则该方法被视为重载而不是重写。

3.4)访问修饰符的不同

方法重载和方法重写中访问修饰符的使用是不同的。

在方法重载中,方法可以具有不同的访问修饰符,但必须在同一类中。这是因为方法重载只涉及到同一类的语意和约定,所以不需要继承(或子类扩展)的概念。

而在方法重写中,子类必须使重写方法的访问修饰符“不小于”父类的访问修饰符。这是因为子类继承了父类的所有特性,包括其访问修饰符设置。如果重写方法的访问修饰符小于父类的访问修饰符,那么该方法只能通过父类调用并隐式继承其访问修饰符。

结论

在JAVA编程中,方法重载和重写是两个重要的概念,它们虽然看起来类似,但是它们的语法和语义都有很大的区别。方法重载是在同一个类中,有多个相同名称的方法,但参数列表不同,以实现不同的功能。而方法重写是在子类中重新定义父类中已有的方法,以实现对该方法的修改或扩展。在实际编程中,快速理解和正确运用这两个概念是非常重要的。