Java中的多态

本文介绍了Java中的多态性,包括多态的定义、使用前提条件以及两种主要形式——向上转型和向下转型。多态提高了代码的可重用性和扩展性,但可能丢失子类特有属性。向上转型允许将子类对象作为父类处理,而向下转型能访问子类特有的方法,但存在类型转换异常的风险。

多态



Java中为什么要有多态

Java中使用多态的主要目的是提高代码的可重用性和扩展性,使得代码更加灵活和易于维护。通过多态,我们可以将不同的对象看做是同一种类型,从而使得我们可以使用同一种接口来操作这些对象,而不必关心具体的实现细节。


一、多态的定义

多态是面向对象编程中的一个重要概念,它指的是同一个对象在不同情况下具有不同的表现形式和功能。在Java中,多态是指同一个类型的对象,在不同的情况下可以表现出不同的行为。

二、使用多态的前提条件

1.使用条件

1.必须在继承体系下,子类必须继承父类
2.子类必须要对父类中方法进行重写
3.通过父类的引用调用重写的方法 (对于重写不在此处介绍)

2.代码示例

class Animal {
   public void sound() {
      System.out.println("The animal makes a sound");
   }
}

class Cat extends Animal {
   public void sound() {
      System.out.println("The cat meows");
   }
}

class Dog extends Animal {
   public void sound() {
      System.out.println("The dog barks");
   }
}

public class Main {
   public static void main(String[] args) {
      Animal myAnimal = new Animal();
      Animal myCat = new Cat();
      Animal myDog = new Dog();
      
      myAnimal.sound();
      myCat.sound();
      myDog.sound();
   }
}

在这个例子中,Animal是一个父类,而Cat和Dog是它的子类。在main方法中,我们创建了一个Animal对象,一个Cat对象和一个Dog对象。然后,我们通过调用它们的sound方法来展示不同的行为。由于myCat和myDog是Animal类型的引用,但是它们指向的是Cat和Dog对象,因此在调用sound方法时会表现出不同的行为,这就是多态的体现。

当代码运行时的结果是:
在这里插入图片描述


三、多态的两种形式–向上转型和向下转型

1.向上转型

a.代码示例

class Animal {
   public void sound() {
      System.out.println("The animal makes a sound");
   }
}

class Cat extends Animal {
   public void sound() {
      System.out.println("The cat meows");
   }
}

class Dog extends Animal {
   public void sound() {
      System.out.println("The dog barks");
   }
}

public class Main {
   public static void main(String[] args) {
      Animal myAnimal = new Animal();
      Animal myCat = new Cat();
      Animal myDog = new Dog();
      
      myAnimal.sound();
      myCat.sound();
      myDog.sound();
   }
}

r

b.详细解释

Java中的向上转型是指一个子类对象赋值给一个父类类型的变量。这个过程是隐式的,不需要强制类型转换。

向上转型:实际就是创建一个子类对象,将其当作父类对象来用

//伪代码
语法格式:父类类型 对象名 = new 子类类型();

//例如上面的示例代码
      Animal myAnimal = new Animal();
      Animal myCat = new Cat();
      Animal myDog = new Dog();
      

比如上面的代码。myAnimal 是父类类型,但是可以引用一个子类对象,因此从小范围向大范围的转换。

c.优缺点

1.优点:提高代码的灵活性和可扩展性

向上转型的主要作用是提高代码的灵活性和可扩展性。通过向上转型,我们可以将一个具体的子类对象看做是一个更为抽象的父类对象,从而使得我们可以使用更为通用的方法和接口来操作这些对象。这样,我们就可以在不改变原有代码的情况下,轻松地扩展程序的功能,增加新的子类对象。

2.缺点:可能会丢失子类特有的方法和属性

向上转型的缺点是可能会丢失子类特有的方法和属性。由于父类类型的变量不能访问子类特有的方法和属性,因此在进行向上转型时,这些方法和属性会被隐藏起来。如果我们需要使用这些特有的方法和属性,就需要进行向下转型。另外,由于向上转型是隐式的,因此可能会导致代码的可读性降低。

2.向下转型

a.代码示例

class Animal {
   public void sound() {
      System.out.println("The animal makes a sound");
   }
}

class Cat extends Animal {
   public void sound() {
      System.out.println("The cat meows");
   }
   
   public void scratch() {
      System.out.println("The cat scratches");
   }
}

class Dog extends Animal {
   public void sound() {
      System.out.println("The dog barks");
   }
   
   public void fetch() {
      System.out.println("The dog fetches");
   }
}

public class Main {
   public static void main(String[] args) {
      Animal myAnimal = new Cat();
      
      myAnimal.sound();
      
      if (myAnimal instanceof Cat) {
         Cat myCat = (Cat) myAnimal;
         myCat.scratch();
      }
   }
}

在这里插入图片描述
在这个例子中,我们创建了一个Animal类型的变量myAnimal,并将其赋值为一个Cat对象。然后,我们调用myAnimal的sound方法,输出"the cat meows"。接着,我们使用instanceof运算符来检查myAnimal是否是Cat类型的对象。由于myAnimal指向的是一个Cat对象,因此instanceof运算符返回true。然后,我们使用强制类型转换将myAnimal转换为Cat类型的变量myCat,并调用它的scratch方法,输出"The cat scratches"。这就是多态的向下转型的体现。

b.详细解释

Java中的向下转型是指将一个父类类型的变量强制转换为一个子类类型的变量。向下转型需要进行强制类型转换,如果转换失败会抛出ClassCastException异常。

向下转型的实质是一个父类类型的变量强制转换为一个子类类型的变量

语法格式

public class Main {
    public static void main(String[] args) {
        Animal myAnimal = new Cat();
        myAnimal.sound();
        
        Cat myCat = (Cat) myAnimal;
    }
}

但是向下转型也会带来问题,比如在下面的代码中

public class Main {
    public static void main(String[] args) {
        Animal myAnimal = new Cat();
        Animal myAnimal1 = new Dog();

        myAnimal.sound();
        myAnimal1.sound();

        Cat myCat = (Cat) myAnimal;
        Cat myCat1 = (Cat) myAnimal1;

        myCat.scratch();
        myCat1.scratch();
    }
}

当运行下面的代码的时候,程序可以通过编程,但是运行的时候就会报错

在这里插入图片描述
这是myAnimal1实际上指向的是狗,现在要强制还原成为猫,无法正常还原,所以运行时抛出异常ClassCastException

Java中为了提高向下转型的安全性,引入了 instanceof ,如果该表达式为true,则可以安全转换。

public class Main {
   public static void main(String[] args) {
      Animal myAnimal = new Cat();
      
      myAnimal.sound();
      
      if (myAnimal instanceof Cat) {
         Cat myCat = (Cat) myAnimal;
         myCat.scratch();
      }
   }
}

instanceof运算符是一种检查对象类型的运算符,它可以用来判断一个对象是否是某个类的实例。它的优点是可以避免类型转换异常,因为它可以在转换之前先判断对象类型是否正确。缺点是需要额外的代码来进行判断,从而可能会导致代码的复杂性增加。

c.优缺点

1.优点:可以获取子类独有的方法和属性

向下转型的优点是可以获取子类独有的方法和属性,从而可以对子类进行更为具体的操作。同时,向下转型可以使得程序更加灵活和可扩展,可以在不改变原有代码的情况下,增加新的子类对象。

2.缺点:可能会导致类型转换异常

向下转型的缺点是可能会导致类型转换异常,因为父类类型的变量并不一定都可以转换为子类类型的变量。另外,向下转型也会破坏程序的封装性,因为它可以直接访问子类的方法和属性,从而可能导致一些安全问题。


总结

多态可以提高代码的可重用性,扩展性和灵活性,但是代码的运行效率会降低,比属性没有多态性,当父类和子类都有同名属性的时候,通过父类引用时,只能调用父类自己的成员属性。

### 多态的基本概念 多态是面向对象编程中的一个核心特性,它允许子类对象替换父类对象。这意味着可以使用父类的引用指向子类的对象,并调用在子类中重写的方法[^1]。 ### 多态的具体体现 多态主要体现在方法的覆盖(也称为重写)上,即子类可以提供特定于自身的实现,而这些实现可以在不改变接口的情况下被调用[^1]。 ### 入门案例 考虑一个简单的例子,我们有一个`Animal`类,它有一个`sound()`方法。我们可以创建`Dog`和`Cat`类作为`Animal`的子类,并重写`sound()`方法来发出不同的声音。 ```java class Animal { void sound() { System.out.println("Animal makes a sound"); } } class Dog extends Animal { void sound() { System.out.println("Barking..."); } } class Cat extends Animal { void sound() { System.out.println("Meowing..."); } } ``` 在这个例子中,尽管`myAnimal`是一个`Animal`类型的引用,但它可以指向`Dog`或`Cat`的对象,并且会调用相应对象的`sound()`方法。 ### 多态的转型 #### 向上转型 向上转型是指将子类对象赋值给父类引用的过程,这是自动完成的,不需要显式的转换。 ```java Animal myAnimal = new Dog(); // Upcasting ``` #### 向下转型 向下转型是指将父类引用转换为子类类型的过程,这需要显式的转换,并且只有当引用实际上指向的是该子类的一个实例时才是合法的。 ```java Animal myAnimal = new Dog(); Dog dog = (Dog) myAnimal; // Downcasting ``` #### 代码示例 ```java public class TestPolymorphism { public static void main(String[] args) { Animal myAnimal = new Animal(); // Animal object Animal myDog = new Dog(); // Animal reference but Dog object Animal myCat = new Cat(); // Animal reference but Cat object myAnimal.sound(); myDog.sound(); // Runs Dog's sound method myCat.sound(); // Runs Cat's sound method } } ``` #### 转型的异常 ##### 类型转换异常 如果尝试将一个对象转换为其实际类型不是的目标类型,则会抛出`ClassCastException`。 ```java Animal myAnimal = new Animal(); Dog dog = (Dog) myAnimal; // Throws ClassCastException ``` ##### `instanceof` 比较操作符 为了避免`ClassCastException`,可以使用`instanceof`关键字来检查对象是否是指定类型。 ```java if (myAnimal instanceof Dog) { Dog dog = (Dog) myAnimal; } ``` ### 动态绑定(重点) 动态绑定(或后期绑定)指的是在运行时根据对象的实际类型来决定调用哪个方法的过程。这是多态的基础,也是Java中实现多态的关键机制。 ### 应用 #### 多态数组 多态数组指的是可以存储不同子类对象的数组,而数组的声明类型是它们共同的父类。 ```java Animal[] animals = new Animal[3]; animals[0] = new Dog(); animals[1] = new Cat(); animals[2] = new Animal(); for (Animal animal : animals) { animal.sound(); } ``` #### 多态参数 多态参数允许方法接受任何子类类型的参数,从而实现更通用的设计。 ```java public void makeSound(Animal animal) { animal.sound(); } ``` ### 多态的优点 - **可扩展性**:可以轻松添加新的子类而无需修改现有代码。 - **可维护性**:由于代码更加通用,因此更容易维护。 - **代码复用**:可以通过继承复用代码,并通过多态提供灵活性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值