将一个类型强制转换成另一个类型的过程被称为类型转换。对象类型转换,是指存在继承关系的对象,不是任意类型的对象。当对不存在继承关系的对象进行强制类型转换时,会抛出 Java 强制类型转换(java.lang.ClassCastException)异常。
1)向上转型
父类引用指向子类对象为向上转型
向上转型就是把子类对象直接赋给父类引用,不用强制转换。使用向上转型可以调用父类类型中的所有成员,不能调用子类类型中特有成员,最终运行效果看子类的具体实现。
2)向下转型
与向上转型相反,子类对象指向父类引用为向下转型
向下转型可以调用子类类型中所有的成员,不过需要注意的是如果父类引用对象指向的是子类对象,那么在向下转型的过程中是安全的,也就是编译是不会出错误。但是如果父类引用对象是父类本身,那么在向下转型的过程中是不安全的,编译不会出错,但是运行时会出现我们开始提到的 Java 强制类型转换异常,一般使用 instanceof 运算符来避免出此类错误。
例如,Animal 类表示动物类,该类对应的子类有 Dog 类,使用对象类型表示如下:
- Animal animal = new Dog(); // 向上转型,把Dog类型转换为Animal类型
- Dog dog = (Dog) animal; // 向下转型,把Animal类型转换为Dog类型
例 1
下面通过具体的示例演示对象类型的转换。例如,父类 Animal 和子类 Cat 中都定义了实例变量 name、静态变量 staticName、实例方法 eat() 和静态方法 staticEat()。此外,子类 Cat 中还定义了实例变量 str 和实例方法 eatMethod()。
父类 Animal 的代码如下:
public class Animal {
public String name = "Animal:动物";
public static String staticName = "Animal:可爱的动物";
public void eat() {
System.out.println("Animal:吃饭");
}
public static void staticEat() {
System.out.println("Animal:动物在吃饭");
}
}
子类 Cat 的代码如下:
public class Cat extends Animal {
public String name = "Cat:猫";
public String str = "Cat:可爱的小猫";
public static String staticName = "Dog:我是喵星人";
public void eat() {
System.out.println("Cat:吃饭");
}
public static void staticEat() {
System.out.println("Cat:猫在吃饭");
}
public void eatMethod() {
System.out.println("Cat:猫喜欢吃鱼");
}
public static void main(String[] args) {
Animal animal = new Cat();
Cat cat = (Cat) animal; // 向下转型
System.out.println(animal.name); // 输出Animal类的name变量
System.out.println(animal.staticName); // 输出Animal类的staticName变量
animal.eat(); // 输出Cat类的eat()方法
animal.staticEat(); // 输出Animal类的staticEat()方法
System.out.println(cat.str); // 调用Cat类的str变量
cat.eatMethod(); // 调用Cat类的eatMethod()方法
}
}
通过引用类型变量来访问所引用对象的属性和方法时,Java 虚拟机将采用以下绑定规则:
- 实例方法与引用变量实际引用的对象的方法进行绑定,这种绑定属于动态绑定,因为是在运行时由 Java 虚拟机动态决定的。例如,animal.eat() 是将 eat() 方法与 Cat 类绑定。
- 静态方法与引用变量所声明的类型的方法绑定,这种绑定属于静态绑定,因为是在编译阶段已经做了绑定。例如,animal.staticEat() 是将 staticEat() 方法与 Animal 类进行绑定。
- 成员变量(包括静态变量和实例变量)与引用变量所声明的类型的成员变量绑定,这种绑定属于静态绑定,因为在编译阶段已经做了绑定。例如,animal.name 和 animal.staticName 都是与 Animal 类进行绑定。
对于 Cat 类,运行时将会输出如下结果:
Animal:动物 Animal:可爱的动物 Cat:吃饭 Animal:动物在吃饭 Cat:可爱的小猫 Cat:猫喜欢吃鱼