Java中的多态是指一个接口可以表示多种不同的实现方式,或者一个变量、方法或对象可以在程序的不同部分表示不同的类型。
Java中的多态允许一个类的实例可以被当作其父类或其他接口类型的引用来使用。这意味着可以编写更加通用的代码,这些代码可以接受不同类型的对象而不必知道它们的具体类型。
一、多态的表现方式
继承
在Java中,一个类可以从另一个类继承属性和方法。当一个子类继承自一个父类时,它可以重写(override)父类的方法以提供特定的行为。这样,即使你使用的是父类的引用,调用方法时也会根据实际的对象类型来决定执行哪个方法。
接口
Java中的接口定义了一组方法签名,任何实现了该接口的类必须提供这些方法的实现。这样,你可以通过接口类型的引用来调用方法,而不需要知道具体实现这些方法的类是什么。
向上转型
将子类对象赋值给父类类型的变量。由于Java是单继承的语言,一个类只能直接继承自一个父类,但这并不限制一个类可以作为多种类型被看待,尤其是通过接口实现。
二、向上转型相关代码示例
Person 和 User,其中 User 继承自 Person。当你在一个 List<Person> 中存储 User 对象时,由于 User 是 Person 的子类,理论上不会丢失数据。但是,你会失去对 User 类中新增属性的访问能力,除非你显式地将 Person 引用向下转型为 User。
这里有几个要点需要注意:
-
属性丢失:
如果User类中添加了一些新的属性,这些属性不会在List<Person>中丢失。但是,当你通过List<Person>访问这些对象时,你只能看到Person类中定义的属性,而无法直接访问User类中特有的属性。 -
方法丢失:
同样地,如果User类中添加了新的方法,这些方法不会丢失,但你只能通过User的引用访问这些方法。如果你通过Person的引用访问对象,你只能调用Person类中的方法。 -
类型安全:
如果你尝试将一个非User类型的对象放入List<Person>中,当你尝试将它作为User使用时,可能会抛出ClassCastException。
假设你有两个类:
class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
class User extends Person {
private String username;
private String password;
public User(String name, String username, String password) {
super(name);
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
}
现在,假设你有一个 List<Person>,你可以在其中存储 User 对象:
List<Person> personList = new ArrayList<>();
personList.add(new User("John Doe", "johndoe", "password123"));
personList.add(new User("Jane Doe", "janedoe", "secret456"));
接下来,你可以访问 Person 类中的属性,但无法直接访问 User 类中的属性:
personList.forEach(person -> System.out.println(person.getName())); // 输出 "John Doe" 和 "Jane Doe"
// 尝试访问 User 类中的特定属性
personList.forEach(person -> System.out.println(((User) person).getUsername())); // 抛出 ClassCastException 如果 person 不是 User 类型
为了安全地访问 User 类中的特定属性,你可以使用 instanceof 关键字进行类型检查:
personList.forEach(person -> {
if (person instanceof User) {
User user = (User) person;
System.out.println(user.getUsername()); // 输出 "johndoe" 和 "janedoe"
}
});
三、总结
- 数据本身不会丢失,只是访问受限于父类引用所能看到的部分。
- 为了访问子类特有的属性和方法,你需要显式地向下转型。
- 使用
instanceof关键字可以避免ClassCastException。
四、注意事项
- 向上转型:将子类对象赋值给父类引用是自动的,称为向上转型(upcasting)。
- 向下转型:如果您需要访问子类特有的方法或属性,需要显式地将父类引用向下转型为子类类型。例如,
((子类) 对象名).子类方法();。 - 运行时类型检查:在进行向下转型之前,通常会使用
instanceof关键字来检查对象是否是预期的子类类型。
782

被折叠的 条评论
为什么被折叠?



