Java中多态相关的要点和细节注意

1、Java中为什么多态使用父类型做参数,可以接收所有子类对象,但是反过来却不行呢?

这个问题涉及到Java中的多态性(polymorphism)和继承(inheritance)。为了理解为什么父类型可以接收所有子类对象,而反过来却不行,我们需要深入了解面向对象编程中的类型兼容性

1. 多态性与继承:父类可以接收子类对象

在Java中,多态性是指一个对象可以以多种形式表现。在继承关系中,子类对象可以被赋值给父类类型的引用变量,这叫做向上转型(upcasting)。

原因:子类继承了父类的所有非私有方法和属性,因此它至少具备了父类的特性(方法和属性)。这样,父类类型的引用变量可以安全地指向任何子类对象。

这符合面向对象编程中的"里氏替换原则"(Liskov Substitution Principle,LSP),即任何能够使用父类对象的地方都应该能够使用子类对象,而不影响程序的正确性。

代码示例:

// 父类
class Animal {
    void sound() {
        System.out.println("动物发出声音");
    }
}

// 子类
class Dog extends Animal {
    @Override
    void sound() {
        System.out.println("狗汪汪叫");
    }
}

class Cat extends Animal {
    @Override
    void sound() {
        System.out.println("猫喵喵叫");
    }
}

public class Main {
    public static void main(String[] args) {
        // 父类引用可以指向子类对象
        Animal myDog = new Dog();
        Animal myCat = new Cat();

        // 调用子类的重写方法
        myDog.sound();  // 输出: 狗汪汪叫
        myCat.sound();  // 输出: 猫喵喵叫
    }
}

解释

  • 在这里,Animal是父类,DogCat是子类。
  • Animal myDog = new Dog();Animal myCat = new Cat(); 是典型的向上转型,父类引用Animal指向子类对象DogCat
  • 虽然引用类型是Animal,但由于多态性,程序会根据实际对象的类型来调用DogCatsound()方法(动态绑定)。

2. 为什么子类不能接收父类对象?

相反,子类类型不能指向父类对象,这叫做向下转型(downcasting),它并不是自动安全的。因为父类可能不具备子类的特性,所以直接赋值会导致不兼容的情况。

要安全地进行向下转型,必须使用显式的类型转换,并且需要保证父类对象确实是子类实例,否则会发生ClassCastException

原因:子类可能有比父类更多的特性(方法和属性),如果子类引用指向一个父类对象,子类试图调用父类中不存在的方法或属性,就会导致错误。

代码示例:

class Animal {
    void sound() {
        System.out.println("动物发出声音");
    }
}

class Dog extends Animal {
    void bark() {
        System.out.println("狗汪汪叫");
    }
}

public class Main {
    public static void main(String[] args) {
        // 父类引用指向父类对象
        Animal animal = new Animal();
        
        // 子类引用不能直接指向父类对象
        // Dog myDog = animal;  // 编译错误

        // 需要显式进行类型转换(向下转型)
        if (animal instanceof Dog) {
            Dog myDog = (Dog) animal;  // 安全向下转型
            myDog.bark();
        } else {
            System.out.println("animal不是Dog的实例");
        }
    }
}

解释

  • 在上面的代码中,Animal类没有bark()方法,而Dog类有。因此,不能直接将Animal类型的对象赋值给Dog类型引用。
  • 如果试图直接执行Dog myDog = animal;会导致编译错误,因为编译器无法保证animal具有Dog的特性。
  • 使用instanceof关键字可以检查对象的实际类型,在确保对象是Dog实例后,再进行显式的类型转换。

3. 总结

  • 父类可以接收子类对象(向上转型),因为子类具备父类的所有特性,程序员可以放心使用父类的所有方法和属性,而不用担心程序崩溃。
  • 子类不能接收父类对象(向下转型),因为父类可能没有子类特有的方法和属性,这样赋值会导致不兼容性,需要显式地进行类型转换并进行类型检查。
  • Java的多态性允许我们通过父类引用来操作子类对象,这提供了灵活性,尤其在需要处理一组不同的子类对象时,可以统一通过父类接口来处理它们。

 

 2、关于类型强制转换,Java14新引入的特性,写法注意理解和掌握。

 

 

 

 

 

 

 

 

 

 

 

posted @ 2024-10-15 16:10  AlphaGeek  阅读(95)  评论(0)    收藏  举报