Java中的多态是指同一个行为具有多个不同表现形式的能力,简单来说就是父类引用可以指向子类对象,调用同一个方法时,会根据实际指向的对象类型执行不同的逻辑。实现多态需要满足三个核心条件:存在继承或者实现关系、子类重写父类的方法、父类引用指向子类对象。

基于继承和方法重写实现多态
这是最常见的多态实现方式,首先定义父类,在父类中声明需要被重写的方法,然后子类继承父类并重写该方法,最后通过父类引用指向子类对象来触发多态效果。
示例代码
// 定义父类Animal
class Animal {
// 父类中的方法,子类会重写这个方法
public void makeSound() {
System.out.println("动物发出声音");
}
}
// 子类Dog继承Animal
class Dog extends Animal {
// 重写父类的makeSound方法
@Override
public void makeSound() {
System.out.println("汪汪汪");
}
}
// 子类Cat继承Animal
class Cat extends Animal {
// 重写父类的makeSound方法
@Override
public void makeSound() {
System.out.println("喵喵喵");
}
}
public class PolymorphismDemo {
public static void main(String[] args) {
// 父类引用指向子类对象,实现多态
Animal animal1 = new Dog();
Animal animal2 = new Cat();
// 调用同一个方法,执行不同的逻辑
animal1.makeSound(); // 输出:汪汪汪
animal2.makeSound(); // 输出:喵喵喵
}
}上面的代码中,Animal是父类,Dog和Cat是子类,两个子类都重写了makeSound方法。当用Animal类型的引用指向Dog和Cat对象时,调用makeSound方法会自动执行对应子类的实现,这就是多态的体现。
基于接口实现多态
除了继承,通过接口和实现类的方式也能实现多态。先定义接口,在接口中声明抽象方法,然后不同的实现类实现该接口并重写方法,最后用接口类型的引用指向实现类对象。
示例代码
// 定义接口Payment
interface Payment {
// 接口中的抽象方法,用于支付
void pay(double amount);
}
// 支付宝支付实现类
class AliPay implements Payment {
@Override
public void pay(double amount) {
System.out.println("使用支付宝支付:" + amount + "元");
}
}
// 微信支付实现类
class WeChatPay implements Payment {
@Override
public void pay(double amount) {
System.out.println("使用微信支付:" + amount + "元");
}
}
public class PaymentDemo {
public static void main(String[] args) {
// 接口引用指向实现类对象,实现多态
Payment pay1 = new AliPay();
Payment pay2 = new WeChatPay();
pay1.pay(100.0); // 输出:使用支付宝支付:100.0元
pay2.pay(200.0); // 输出:使用微信支付:200.0元
}
}这种方式的好处是降低了代码之间的耦合度,后续如果需要新增支付方式,只需要新增一个实现Payment接口的类即可,不需要修改原有的支付逻辑代码。
多态的注意事项
- 多态只能调用父类中声明的方法,不能调用子类特有的方法,如果需要调用子类特有方法,需要进行向下转型。
- 静态方法不存在多态,因为静态方法属于类,不属于对象,调用时看引用类型的静态方法。
- 成员变量也不存在多态,访问成员变量时看引用类型的成员变量值。
多态的实际应用场景
多态在实际开发中非常常用,比如方法的参数使用父类或者接口类型,这样传入不同的子类或者实现类对象时,方法可以自动适配不同的逻辑,不需要写多个重载方法。例如在上面的支付场景中,可以定义一个统一的方法处理支付:
public class PaymentService {
// 方法参数为Payment接口类型,支持所有实现该接口的对象
public static void processPayment(Payment payment, double amount) {
payment.pay(amount);
}
public static void main(String[] args) {
processPayment(new AliPay(), 150.0);
processPayment(new WeChatPay(), 300.0);
}
}这样的设计让代码的可扩展性更强,后续新增支付方式时不需要修改processPayment方法的逻辑,符合开闭原则。