先回顾一下Java基础:在Java中,任何对象变量的值都是对存储在另外一个地方的一个对象的引用。一个对象变量并没有实际包含一个对象,而仅仅是引用了一个对象。
A a = new A();
表达式 new A()构造了一个A类型的对象,它的返回值也是一个引用,是对新创建对象的引用。我们把这个引用存储在A类型的变量a中。
向上转型:将一个子类的引用赋给一个超类变量。这是安全的,不用进行强制类型转换。
例如:Father f = new Son();
缺点:导致一些方法和属性的丧失。f现在只能调用Father类中定义的方法和属性,对Son类中方法和属性就望尘莫及了。
向下转型:将一个超类的引用赋给一个子类变量,必须进行类型转换。
例如:
Father f = new Son();
Son s = (Son)f;
向下转型是不安全的,因为可能存在“谎报”对象的情况,例如
Father f = new Father();
Son s = (Son)f;
运行上面这个程序将会抛出:java.lang.ClassCastException异常。
下面是一个小例子供参考:
public class Person{
public static void main(String[] args){
Manager m1 = new Manager("zhu",8000,2000);
Employee e1 = new Manager("li",8000,1000);
Employee e2= new Employee("zhang",8000);
Employee e = (Manager)m1; //向上转型
Manager m = (Manager)e1; //向下转型,这是正确的,运行时也不报错
m = (Manager)e2; //向下转型,这是不正确的,属于谎报对象,编译可以过,但运行时报错
}
}
/**
* 员工类
* @author rttd
*
*/
class Employee{
private String name;
private double salary;
public Employee(String aName, double aSalary){
name = aName;
salary = aSalary;
}
public Employee(){
this("",0);
}
public void raiseSalary(double percent){
double raise = this.salary*percent/100;
this.salary += raise;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void getSalary(int a){
System.out.println("我是员工类,是经理类的父类噢");
}
public void setSalary(double salary) {
this.salary = salary;
}
}
/**
* 经理类,属于员工类的子类
* @author rttd
*
*/
class Manager extends Employee{
private double bonus;
public Manager(String aName,double aSalary,double aBonus){
super(aName, aSalary);
this.bonus = aBonus;
}
public Manager(){
this("",0,0);
}
public double getSalary(){
double base = super.getSalary();
return base + bonus;
}
public void getSalary(int a){
System.out.println("我是经理类,是员工类的子类");
}
}
因为Java有多态的特性,所以大多数时候,调用有继承关系的对象的方法时,我们都可以利用动态绑定机制自动的找到对应的方法。当必须要用强制类型转换调用一些子类中特定的方法时,要注意考虑一下安全性。关于Java的多态特性,可以看看这篇帖子。