如上文中:
Cat c = new Cat();
Object obj = c;
如上例,我们不能把obj当成一只猫去访问,猫自己独有而Object类没有的成员,obj就不能访问了。
public class Test {
public static void main(String[] args) {
Object obj = new Object();
Cat cat = new Cat();
System.out.println(cat instanceof Cat);//true
System.out.println(cat instanceof Object);//true
System.out.println("----------------------");
System.out.println(obj instanceof Object);//true
System.out.println(obj instanceof Cat);//false
System.out.println("----------------------");
/* 父类引用指向子类对象 */
obj = cat;
System.out.println(obj instanceof Object);//true
System.out.println(obj instanceof Cat); //true
}
}
class Cat {
String eyesColor;
}
运行结果已注释在打印语句之后。
四、父类引用指向子类对象称作向上转型(upcasting),父类引用类型变量强制类型转换为子类引用类型变量称为向下转型(downcasting).
见下例:class Animal {
public String name;
Animal(String name) {
this.name = name;
}
}
class Cat extends Animal {
public String eyesColor;
Cat(String name, String eyesColor) {
super(name);
this.eyesColor = eyesColor;
}
}
class Dog extends Animal {
public String furcolor;
Dog(String name, String furColor) {
super(name);
this.furcolor = furColor;
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Animal("name");
Cat c = new Cat("catname", "blue");
Dog d = new Dog("dogname", "black");
/* 引用型变量所指向的对象属于该类 */
System.out.println(a instanceof Animal);//true
/* 引用型变量所指向的对象属于该类的子类 */
System.out.println(c instanceof Animal);//true
System.out.println(d instanceof Animal);//true
/* false!父类引用指向的父类对象没有指向子类对象
* 因此不属于子类
*/
System.out.println(a instanceof Cat);//false
/*
* a可以看做是一个指向Dog类对象的一个引用,但由于a原来是
* Animal这个父类的对象的引用,因此a并不是真正意义上的
* Dog类的对象的引用,a无法访问Dog类新增的成员。
* 总结:a是一个只能访问父类部分、不能访问子类部分的指向子类对象的引用。
*/
a = new Dog("bigyellow", "yellow"); //向上转型
System.out.println(a.name);//bigyellow
/*
* 虽然父类引用可以指向子类对象,
* 但是父类引用不能访问其子类对象新增加的成员(属性和方法)
* System.out.println(a.furColor);//!error
*/
/*
* 由于a是一个只能访问父类部分、不能访问子类部分的指向子类对象的引用。
* 但a在访问子类部分内容时是受限的,但a的确是指向Dog类的对象,该
* 对象属于Animal的子类Dog类
*/
System.out.println(a instanceof Animal);//true
/*
* 引用a的确是指向Dog类对象的,该对象属于Dog类
*/
System.out.println(a instanceof Dog);//true
Dog d1 = (Dog)a; //向下转型,强制类型转换
System.out.println(d1.furcolor);//yellow
}
}
运行结果已注释在打印语句之后。
该程序的部分内存图如下图所示:
Animal a = new Animal("name"); //引用a本来是指向一个Animal类对象的。
a = new Dog("bigyellow", "yellow"); //让父类引用a指向子类对象,称为向下转型(downcasting)。
a所指向的这个子类对象中:父类成员变量name初始值为"bigyellow",子类成员变量furColor初始值为"yellow"。
虽然a指向了子类Dog对象,但它是Animal类型的引用,所以即便指向子类Dog对象,a也只看到了其中的父类部分(如图中虚线箭头所示)。
因此只能通过a.name的方式访问父类部分的name,而无法通过a.furColor的方式去访问子类部分的furColor。
Dog d1 = (Dog)a; //将a从Animal类型强制类型转换为Dog类型,从父类类型转换到子类类型,称为向下转型(downcasting)。
在引用d1与a一样可以指向该对象时,因为引用d1是Dog类型的,它当然可以看到整个对象(包括子类部分),所以d1.furColor是合法的。