多态
同类型的对象表现出的不同形态
多态的表现形式
父类类型 对象名称 = 子类对象
多态实现的条件
-
子类继承父类,并且子类重写父类方法
-
父类引用指向子类对象。(父类引用可以指向任意一个子类的对象)
-
方法重写是基础
-
父类引用调用方法时,实际上调用的是子类的方法(父类指向哪个子类就调用的哪个子类的方法),不同的子类有不同的方法实现,体现出同一个方法在不同子类中的不同形态的表现。
多态调用成员的特点
-
变量调用:编译看左边,运行也看左边
-
Animal dog = new Dog();这个语句的左边或者右边
javac
编译代码的时候,会看左边有没有这个变量,如果有编译成功,如果没有编译失败。运行的时候,会获取左边父类的成员变量的值
public class Animal {
String name = "动物";
public void show() {
System.out.println("Animal");
}
}
public class Dog extends Animal{
String name = "狗";
@Override
public void show() {
System.out.println("狗方法");
}
}
public class Cat extends Animal{
String name = "猫";
@Override
public void show() {
System.out.println("猫方法");
}
}
public class AnimalTest {
public static void main(String[] args) {
//创建对象
Animal dog = new Dog();
System.out.println(dog.name);
Animal cat = new Cat();
System.out.println(cat.name);
}
}
运行结果是:
动物
动物
-
方法调用:编译看右边,运行看右边
-
javac
编译代码的时候,会看左边有没有这个变量,如果有编译成功,如果没有编译失败。运行的时候,会获取右边子类的成员变量的值
子类、父类同上
public class AnimalTest {
public static void main(String[] args) {
//创建对象
Animal dog = new Dog();
dog.show();
Animal cat = new Cat();
cat.show();
}
}
运行结果
狗方法
猫方法
多态的好处
使用父类作为参数,就可以接受所有子类对象,体现多态的扩展性与便利
对象数组的使用
在Java中,我们可以创建包含对象的数组。对象数组是一种特殊类型的数组,其中每个元素都是一个对象的引用。你可以将任何类的对象存储在对象数组中,并通过索引来访问和操作这些对象。
使用格式:
// 创建对象数组
ClassName[] arrayName = new ClassName[size];
// 实例化对象并存储到数组中
arrayName[index] = new ClassName();
// 访问对象数组中的元素
ClassName obj = arrayName[index];
// 修改对象数组中的元素
arrayName[index].propertyName = value;
例:
class Person {
String name;
int age;
}
public class Main {
public static void main(String[] args) {
// 创建对象数组
Person[] people = new Person[3];
// 实例化对象并存储到数组中
people[0] = new Person();
people[0].name = "Alice";
people[0].age = 25;
people[1] = new Person();
people[1].name = "Bob";
people[1].age = 30;
people[2] = new Person();
people[2].name = "Charlie";
people[2].age = 35;
// 访问对象数组中的元素
System.out.println("Name: " + people[0].name + ", Age: " + people[0].age);
System.out.println("Name: " + people[1].name + ", Age: " + people[1].age);
System.out.println("Name: " + people[2].name + ", Age: " + people[2].age);
}
}
使用对象作为方法的参数
在Java中,我们可以将对象作为方法的参数传递。这对于需要传递多个相关数据的情况非常有用。通过将对象作为参数传递给方法,我们可以方便地访问和操作该对象的属性。
class Person {
String name;
int age;
}
public class Main {
public static void printPersonInfo(Person person) {
System.out.println("Name: " + person.name + ", Age: " + person.age);
}
public static void main(String[] args) {
Person person = new Person();
person.name = "Alice";
person.age = 25;
// 调用方法,并传递对象作为参数
printPersonInfo(person);
}
}
instanceof
的使用
instanceof
是 Java 中的关键字,用于判断一个对象是否是某个类的实例或子类的实例。它可以用来做类型检查和类型转换。
示例代码:
Animal cat = new Cat();
if (cat instanceof Cat) {
System.out.println("cat is an instance of Cat");
}
if (cat instanceof Animal) {
System.out.println("cat is an instance of Animal");
}
向上转型
子类向父类转换 称为向上转型。它是一种隐式的类型转换,在继承关系存在的情况下可以自动进行。
格式:
父类类型 引用变量 = new 子类类型();
调用实例方法是,要看是哪个对象调用的就执行哪个方法,调用 static 方法时,调用的是父类方法(静态方法属于类)实例方法看等号右边,静态方法看等号左边
。
例:
Pet pet = new Dog();
pet.toHospital();
将pet
向上转型成Dog
-
只能调用父类声明的方法,子类扩展的方法不能调用
-
调用实例方法时,看是那个对象调用就执行哪个对象的方法
向下转型
如果想调用子类新增的方法,可以通过把父类转换成子类实现,称为向下转型,必须通过强制转型实现
格式:
子类类型 引用变量类型 = (子类类型) 父类类型的引用变量;
在进行向下转型之前,应先使用
instanceof
运算符进行类型检查,以确保转型是安全的。
-
使用 instanceof 时,对象的类型必须和 instanceof 后面的参数所指定的类有继承关系,否则会出现编译错误。
-
在 java16 的增强之后,对于 instanceof 的判断以及类型转换可以合二为一,如下:
if (pet instanceof Dog dog) {
dog.catchingFlyDisc();
}
if (pet instanceof Brid bird) {
brid.fly();
}
向下转型实例:
Animal animal = new Cat(); // 向上转型
Cat cat;
if (animal instanceof Cat) { // 类型检查
cat = (Cat) animal; // 向下转型
// 访问和操作Cat类特有的属性和方法
}
编译时多态(重载)
在编译阶段根据方法的参数类型和数量来决定调用哪个方法。多个同名方法通过参数列表来区分。例如,重载的print()
方法可以接受不同类型的参数,并根据参数类型的不同执行不同的代码逻辑。
class Printer {
public void print(String str) {
System.out.println("Printing string: " + str);
}
public void print(int num) {
System.out.println("Printing number: " + num);
}
}
public class Main {
public static void main(String[] args) {
Printer printer = new Printer();
printer.print("Hello");
printer.print(123);
}
}
运行时多态(重写)
在程序运行时根据对象的实际类型来决定调用哪个方法。子类可以重写(覆盖)父类的方法,并改变其行为。通过使用父类类型的引用来引用子类类型的对象,可以实现多态。
class Animal {
public void makeSound() {
System.out.println("Animal is making a sound");
}
}
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Cat is meowing");
}
}
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Dog is barking");
}
}
public class Main {
public static void main(String[] args) {
Animal animal1 = new Cat(); // 向上转型
Animal animal2 = new Dog(); // 向上转型
animal1.makeSound(); // 调用Cat类的makeSound方法
animal2.makeSound(); // 调用Dog类的makeSound方法
}
}