Java中的重写(Override)和多态(Polymorphism)是两个核心概念,它们在面向对象编程中扮演着非常重要的角色。下面我将对这两个概念进行详细的对比分析,包括它们的区别、联系以及应用场景,并附上相应的代码示例。
1.1. 重写(Override)
定义:
重写是子类对父类中允许访问的且非final的实例方法的一种覆盖。子类的方法名和参数列表必须与父类中被重写的方法名和参数列表相同,并且子类方法的返回类型必须与父类方法返回类型相同或是其子类。重写时,子类方法的访问权限不能低于父类方法的访问权限。
应用场景:
当子类需要改变或扩展父类的某个方法的行为时,可以使用重写。这允许子类根据自身的需求提供特定的实现。
示例代码1:
1.1.1
class Animal {
public void makeSound() {
System.out.println("The animal makes a sound");
}
}
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("The dog barks");
}
}
public class Main {
public static void main(String[] args) {
Animal myDog = new Dog();
myDog.makeSound(); // 输出 "The dog barks"
}
}
示例代码2:
1.1.2
A.java
public class A {
public static void test(){
System.out.println("A->test()");
}
}
B.java
public class B extends A{
public static void test(){
System.out.println("B->test()");
}
}
OverrideDemo01.java
public class OverrideDemo01 {
public static void main(String[] args) {
B b = new B();
b.test();
A a = new B();
a.test();
}
}
结果:
B->test()
A->test()
1.1.3 在test方法中,去掉static ,重写
A.java
public class A {
public void test(){
System.out.println("A->test()");
}
}
B.java
public class B extends A{
public void test(){
System.out.println("B->test()");
}
}
OverrideDemo01.java
public class OverrideDemo01 {
public static void main(String[] args) {
B b = new B();
b.test();
A a = new B();
a.test();
}
}
结果:
B->test()
B->test()
分析:
-
重写:需要有继承关系,子类重写父类的方法
- 方法名必须相同;
- 参数列表必须相同;
- 修饰符:范围可以扩大但不能缩小: public > protected>default>private;
- 抛出的异常:范围,可以被缩小,但不能扩大:ClassNotFoundException ---->Exception(大)
-
重写:子类的方法和父类必须一致,方法体不同;
-
什么需要重写?
- 父类的功能,子类不一定需要,或者不满足
- Alt +Insert
1.2. 多态(Polymorphism)
定义:
多态是允许你使用父类类型的引用来引用子类对象。运行时,Java虚拟机(JVM)会根据对象的实际类型来决定调用哪个方法。这是面向对象编程的三大特性之一。
应用场景:
多态常用于实现接口或继承的类之间的通用性。它允许我们编写可重用的代码,而无需关心具体对象的类型。
示例代码1:
1.2.1
class Shape {
public void draw() {
System.out.println("Drawing a generic shape");
}
}
class Circle extends Shape {
@Override
public void draw() {
System.out.println("Drawing a circle");
}
}
class Rectangle extends Shape {
@Override
public void draw() {
System.out.println("Drawing a rectangle");
}
}
public class Main {
public static void main(String[] args) {
Shape[] shapes = new Shape[2];
shapes[0] = new Circle();
shapes[1] = new Rectangle();
for (Shape shape : shapes) {
shape.draw(); // 分别输出 "Drawing a circle" 和 "Drawing a rectangle"
}
}
}
示例代码2:
1.2.2 多态 重写
Person.java
public class Person {
public void run(){
System.out.println("Person run!");
}
}
Stuednt.java
public class Student extends Person {
@Override
public void run() {
// super.run();
System.out.println("Student run!");
}
}
PolymorphicDemo01.java
public class PolymorphicDemo01 {
public static void main(String[] args) {
Student s1 = new Student();
Person s2 = new Student();
s1.run();
s2.run();
}
}
结果:
Student run!
Student run!
1.2.3
Person.java
public class Person {
public void run(){
System.out.println("Person run!");
}
}
Stuednt.java
public class Student extends Person {
// @Override
// public void run() {
// // super.run();
// System.out.println("Student run!");
// }
}
PolymorphicDemo01.java
public class PolymorphicDemo01 {
public static void main(String[] args) {
// 一个对象的实际类型是确定的
// new Student();
// new Person();
// 可以指向的引用类型就不确定了:父类的引用指向子类
// Student 能调用的方法都是自己的或者继承父类的
Student s1 = new Student();
// Person 父类型,可以指向子类,但是不能调用子类独有的方法
Person s2 = new Student();
// 对象能执行哪些方法,需要看左边的类型,和右边关系不大
s1.run();
s2.run();
}
}
结果:
Person run!
Person run!
多态注意事项:
-
- 多态是方法的多态,属性没有多态;
- 父类和子类,有联系 类型转换异常! ClassCastException!
- 存在条件:继承关系,方法需要重写,父类引用指向子类对象!Father f1 = new Son();
- 不能多态的
- Static 方法,属于类,它不属于实例;
- final常量;
- private方法
1.3. 区别和联系
区别:
- 重写:是子类对父类方法的覆盖,关注的是子类如何改变父类的方法行为。
- 多态:是父类引用指向子类对象,关注的是使用统一的接口处理不同的对象。
联系:
- 多态往往依赖于重写。如果子类没有重写父类的方法,那么多态调用时仍会执行父类的方法。
- 重写是多态实现的基础。多态通过方法重写实现运行时方法的动态绑定。
1.4 应用场景说明
重写通常用于扩展或改变父类的行为,而多态则用于实现代码的通用性和扩展性。例如,在一个绘图程序中,你可以定义一个Shape
类作为基类,并定义draw
方法。然后,你可以创建不同的子类如Circle
、Rectangle
等,并重写draw
方法以实现各自的绘制逻辑。在主程序中,你可以使用Shape
类型的数组或集合来存储不同的形状对象,并调用它们的draw
方法。由于多态的特性,你无需关心每个对象的具体类型,只需调用draw
方法即可。这样,你可以轻松地添加新的形状类,而无需修改主程序的代码。
重写和多态的结合使用使得代码更加灵活、可维护和可扩展。通过重写,子类可以提供特定于自己的实现;通过多态,我们可以编写通用的代码来处理不同的对象类型。
1.5. main_args参数测试
public static void main(String[] args) { for (int i = 0; i < args.length; i++) { System.out.println("args["+i+"]:"+args[i]); } } }