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