先上示例代码:
(1)抽象类Person
public abstract class Person {
private String name;
public Person(String name) {
this.name = name;
}
public abstract String getDescription();
public String getName() {
return this.name;
}
}
(2)子类Employee
import java.time.*;
public class Employee extends Person{
private double salary;
private LocalDate hireDay;
public Employee(String name, double salary, int year, int month, int day) {
super(name);
this.salary = salary;
hireDay = LocalDate.of(year, month, day);
}
public double getSalary() {
return this.salary;
}
public LocalDate getHireDay() {
return this.hireDay;
}
public String getDescription() {
return String.format("an employee with salary of $%.2f", this.salary);
}
public void raiseSalary(double byPercent) {
double raise = this.salary * byPercent / 100;
this.salary += raise;
}
}
(3)子类Student
public class Student extends Person{
private String major;
public Student(String name, String major) {
super(name);
this.major = major;
}
public String getDescription() {
return "a student majoring in " + major;
}
}
(4)程序入口
public class Test {
public static void main(String[] args) {
Person[] people = new Person[2];
people[0] = new Employee("Joe Wong", 50000, 1989, 10, 1); // up-casting
people[1] = new Student("Maria Morris", "Computer Science"); // up-casting
for(Person p: people) {
// can only access getName and getDescription
System.out.println(p.getName() + "," + p.getDescription());
}
Employee ref = (Employee)people[0]; // down-casting, because people[0] already refers to an instance of child, OK
System.out.println(ref.getHireDay()); // can now access child's own method, e.g. getHireDay
}
}
比起C++的xxx_cast,Java真是友好多了。简单来讲,子类可以直接被赋给父类(up casting),但是此时该引用只能访问到父类的方法。如果要down casting,前提是父类的引用已经指向了一个子类的实例,例如例子中people[0]已经指向了一个Employee的实例,则cast成功,否则编译器会抛出ClassCastException异常。
进行down casting之前比较好的习惯是先用instancof进行检查:
if(people[0] instanceof Employee) {
Employee ref = (Employee) people[0]; // down-casting, because people[0] already refers to an instance of child, OK
System.out.println(ref.getHireDay()); // can now access child's own method, e.g. getHireDay
}