在Java中,子类可以重写父类中的方法。这是面向对象编程的一个重要特性,它允许子类对父类中继承的方法进行修改或扩展,从而实现更灵活的编程。
1. 什么是方法重写
方法重写(也叫方法覆盖)是指子类中定义与父类中同名、同参数、同返回值类型的方法,从而覆盖(或替换)父类中的方法。当某个方法被子类重写后,调用该方法时,将执行子类中的方法,而不再执行父类中的方法。
使用方法重写,可以让子类继承父类中原有的行为,同时又可以根据子类自身的特性,修改或扩展父类中的方法,使其更符合子类自己的需求。
2. 方法重写的要求
Java中方法重写必须满足以下要求:
- 方法名必须与父类中被重写的方法名相同;
- 方法的参数类型、个数、顺序都必须与被重写的方法相同;
- 返回值类型也必须与被重写的方法相同或者是它的子类;
- 访问修饰符不能比父类中被重写的方法的访问修饰符更严格。
另外,如果父类中被重写的方法是final或private类型的,则不能被子类重写。
3. 方法重写的示例
下面是一个简单的例子,演示了如何在子类中重写父类中的方法:
class Animal { public void makeSound() { System.out.println("动物发出声音"); } } class Cat extends Animal { public void makeSound() { System.out.println("猫发出“喵喵”的声音"); } } public class Main { public static void main(String[] args) { Animal animal = new Cat(); animal.makeSound(); // 输出:猫发出“喵喵”的声音 } }
上面的代码中,Animal类是一个父类,定义了一个名为makeSound的方法;而Cat类继承自Animal类,并覆盖了makeSound方法,使其输出“猫发出‘喵喵’的声音”。
在Main类中,我们实例化了一个Cat对象,并将其赋值给一个Animal引用,这样就可以调用该对象的makeSound方法。由于Cat中重写了makeSound方法,所以输出的是“猫发出‘喵喵’的声音”,而不是Animal中的默认实现。
4. 方法重写的注意事项
4.1 被重写的方法不能为final类型
final修饰的方法是不能被子类重写的。如果在子类中尝试去重写一个final方法,编译器会报错:
class Animal { public final void makeSound() {} } class Cat extends Animal { public void makeSound() {} // 编译错误:makeSound() 无法覆盖 Animal.makeSound();被覆盖的方法为 final }
4.2 方法重写不能改变访问修饰符
方法重写时,访问修饰符不能比父类中被重写的方法的访问修饰符更严格。如果在子类中将父类中被重写的方法声明为private或protected类型,编译器会报错。但是,如果在子类中将父类中的public方法改为protected或private,不会报错,但是也不能通过编译。
class Animal { protected void makeSound() {} } class Cat extends Animal { private void makeSound() {} // 编译错误:makeSound() in Cat cannot override makeSound() in Animal; attempting to assign weaker access privileges; was protected }
4.3 父类和子类里的方法参数要完全一样
父类和子类中重写的方法必须有相同的参数类型、参数个数和顺序。如果不满足这个条件,编译器会报错:
class Animal { public void makeSound(String sound) {} } class Cat extends Animal { public void makeSound(int sound) {} // 编译错误:makeSound(int) in Cat cannot override makeSound(String) in Animal }
4.4 父类和子类里的方法返回类型要匹配
父类和子类中重写的方法的返回类型必须相同,或者子类的返回类型必须是父类的返回类型的子类:
class Animal { public Number makeSound() {return 0;} } class Cat extends Animal { public Integer makeSound() {return 0;} // 编译错误:makeSound() in Cat cannot override makeSound() in Animal; return type Integer is not compatible with Number }
上面的代码中,Animal类中makeSound方法的返回类型是Number,而Cat类中重写的makeSound方法的返回类型是Integer。这是不合法的,因为Integer虽然是Number的子类,但并不等价于Number。
4.5 方法重写时要保证语义一致
在重写父类的方法时,应该保证子类中的方法语义和父类中方法的语义一致。也就是说,重写的方法不能改变原来方法的含义,否则容易出现程序错误。
例如:
class Animal { public void makeSound(int volume) {} } class Cat extends Animal { public void makeSound(int volume, String soundType) {} // 这种覆盖是不一致的,编译错误 }
上面的代码中,Cat类中重写makeSound方法时,添加了一个新的参数soundType,这会导致Cat类的makeSound方法和Animal类的makeSound方法语义不一致。所以编译时会报错。
5. 总结
Java中,方法重写是子类继承父类时的一种特性。它允许子类重写父类中的方法,从而修改或扩展父类中原有的行为。但是,在编写重写方法时需要注意许多细节,包括方法名、访问修饰符、参数类型和顺序、返回类型等。只有遵守这些规则,才能实现正确的方法重写。