- Java教程
- Java - 主页
- Java - 概述
- Java - 环境设置
- Java - 基本语法
- Java - 变量类型
- Java - 基本数据类型
- Java - 基本运算符
- Java 控制语句
- Java - 循环控制
- Java - 决策
- Java - 如果-否则
- Java-开关
- Java - For 循环
- Java - For-Each 循环
- Java - While 循环
- Java - do-while 循环
- Java - 中断
- Java - 继续
- 面向对象编程
- Java - 对象和类
- Java - 方法
- Java - 构造函数
- Java - 访问修饰符
- Java-继承
- Java-多态性
- Java - 重写
- Java-抽象
- Java-封装
- Java - 接口
- Java - 包
- Java - 内部类
- Java 数据类型
- Java - 字符
- Java 文件处理
- Java - 文件和 I/O
- Java 错误与异常
- Java - 异常
- Java多线程
- Java-多线程
- Java同步
- Java-同步
- Java-线程间通信
- Java-线程死锁
- Java-线程控制
- Java网络
- Java-网络
- Java-URL 处理
- Java - 泛型
- Java集合
- Java - 集合
- Java列表接口
- Java - 列表接口
- Java队列接口
- Java - 队列接口
- Java地图接口
- Java - 地图接口
- Java - SortedMap 接口
- Java设置接口
- Java - 设置接口
- Java - SortedSet 接口
- Java数据结构
- Java - 数据结构
- Java-枚举
- Java 集合算法
- Java - 集合
- Java - 迭代器
- Java - 比较器
- Java杂项
- Java - 正则表达式
- Java-序列化
- Java - 发送电子邮件
- Java - Applet 基础知识
- Java - 文档
- Java 有用资源
- Java - 问题与解答
- Java - 快速指南
- Java - 有用的资源
- Java - 讨论
- Java - 示例
Java-多态性
多态性是一个对象呈现多种形式的能力。OOP 中多态性最常见的用法发生在使用父类引用来引用子类对象时。
任何可以通过多个 IS-A 测试的 Java 对象都被认为是多态的。在 Java 中,所有 Java 对象都是多态的,因为任何对象都会通过其自身类型和类 Object 的 IS-A 测试。
重要的是要知道访问对象的唯一可能方法是通过引用变量。引用变量只能是一种类型。一旦声明,引用变量的类型就不能更改。
引用变量可以重新分配给其他对象,前提是它没有声明为final。引用变量的类型将决定它可以在对象上调用的方法。
引用变量可以引用其声明类型的任何对象或其声明类型的任何子类型。引用变量可以声明为类或接口类型。
例子
让我们看一个例子。
public interface Vegetarian{} public class Animal{} public class Deer extends Animal implements Vegetarian{}
现在,Deer 类被认为是多态的,因为它具有多重继承。对于上述示例,以下内容正确 -
- 鹿是一种动物
- 鹿是素食者
- 鹿就是鹿
- 鹿是一个物体
当我们将引用变量事实应用于 Deer 对象引用时,以下声明是合法的 -
例子
Deer d = new Deer(); Animal a = d; Vegetarian v = d; Object o = d;
所有引用变量 d、a、v、o 都引用堆中的同一个 Deer 对象。
例子
在此示例中,我们通过创建 Deer 对象并将其分配给超类或实现的接口的引用来展示上述概念。
interface Vegetarian{} class Animal{} public class Deer extends Animal implements Vegetarian{ public static void main(String[] args) { Deer d = new Deer(); Animal a = d; Vegetarian v = d; Object o = d; System.out.println(d instanceof Deer); System.out.println(a instanceof Deer); System.out.println(v instanceof Deer); System.out.println(o instanceof Deer); } }
输出
true true true true
虚拟方法
在本节中,我将向您展示 Java 中重写方法的Behave如何让您在设计类时利用多态性。
我们已经讨论了方法重写,其中子类可以重写其父类中的方法。重写的方法本质上隐藏在父类中,除非子类在重写方法中使用 super 关键字,否则不会调用该方法。
例子
/* File name : Employee.java */ public class Employee { private String name; private String address; private int number; public Employee(String name, String address, int number) { System.out.println("Constructing an Employee"); this.name = name; this.address = address; this.number = number; } public void mailCheck() { System.out.println("Mailing a check to " + this.name + " " + this.address); } public String toString() { return name + " " + address + " " + number; } public String getName() { return name; } public String getAddress() { return address; } public void setAddress(String newAddress) { address = newAddress; } public int getNumber() { return number; } }
现在假设我们扩展 Employee 类如下 -
/* File name : Salary.java */ public class Salary extends Employee { private double salary; // Annual salary public Salary(String name, String address, int number, double salary) { super(name, address, number); setSalary(salary); } public void mailCheck() { System.out.println("Within mailCheck of Salary class "); System.out.println("Mailing check to " + getName() + " with salary " + salary); } public double getSalary() { return salary; } public void setSalary(double newSalary) { if(newSalary >= 0.0) { salary = newSalary; } } public double computePay() { System.out.println("Computing salary pay for " + getName()); return salary/52; } }
现在,您仔细研究以下程序并尝试确定其输出 -
/* File name : VirtualDemo.java */ public class VirtualDemo { public static void main(String [] args) { Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00); Employee e = new Salary("John Adams", "Boston, MA", 2, 2400.00); System.out.println("Call mailCheck using Salary reference --"); s.mailCheck(); System.out.println("\n Call mailCheck using Employee reference--"); e.mailCheck(); } } class Employee { private String name; private String address; private int number; public Employee(String name, String address, int number) { System.out.println("Constructing an Employee"); this.name = name; this.address = address; this.number = number; } public void mailCheck() { System.out.println("Mailing a check to " + this.name + " " + this.address); } public String toString() { return name + " " + address + " " + number; } public String getName() { return name; } public String getAddress() { return address; } public void setAddress(String newAddress) { address = newAddress; } public int getNumber() { return number; } } class Salary extends Employee { private double salary; // Annual salary public Salary(String name, String address, int number, double salary) { super(name, address, number); setSalary(salary); } public void mailCheck() { System.out.println("Within mailCheck of Salary class "); System.out.println("Mailing check to " + getName() + " with salary " + salary); } public double getSalary() { return salary; } public void setSalary(double newSalary) { if(newSalary >= 0.0) { salary = newSalary; } } public double computePay() { System.out.println("Computing salary pay for " + getName()); return salary/52; } }
输出
Constructing an Employee Constructing an Employee Call mailCheck using Salary reference -- Within mailCheck of Salary class Mailing check to Mohd Mohtashim with salary 3600.0 Call mailCheck using Employee reference-- Within mailCheck of Salary class Mailing check to John Adams with salary 2400.0
在这里,我们实例化两个 Salary 对象。一个使用 Salary 参考资料s,另一个使用 Employee 参考资料e。
在调用s.mailCheck()时,编译器会在编译时在 Salary 类中看到 mailCheck() ,并且 JVM 在运行时调用 Salary 类中的 mailCheck() 。
e上的 mailCheck()非常不同,因为e是 Employee 引用。当编译器看到e.mailCheck()时,编译器会看到 Employee 类中的 mailCheck() 方法。
这里,在编译时,编译器使用 Employee 中的 mailCheck() 来验证该语句。然而,在运行时,JVM 会调用 Salary 类中的 mailCheck()。
这种Behave称为虚拟方法调用,而这些方法称为虚拟方法。无论编译时源代码中使用的引用是什么数据类型,都会在运行时调用重写的方法。