向上转型的概念
- 向上类型转换(Upcast):将子类型转换为父类型
- 即父类引用指向子类实例,也就是子类的对象可以赋值给父类的对象
- 隐式/自动类型转换,是小类型到大类型的转换
- 对于向上的类型转换,不需要显式指定,既不需要加上前面小括号和父类类型名
- 如:
Animal dog = new Dog(); //Dog类时Animal类的子类
向上转型的应用
- 当一个子类对象向上转型父类类型后,就被当成了父类的对象,所能调用的方法会减少,只能调用子类重写了父类的方法以及父类派生的方法,而不能调用子类独有的方法
- 父类中的静态方法是不允许被子类重写的
绑定机制
- 绑定就是将一个方法调用同一个方法所在的类连接在一起就是绑定。绑定分为静态绑定和动态绑定两种
- 静态绑定:在程序运行之前进行绑定(由编译器和链接程序完成的),也叫做前期绑定
- 例:
- 如有一类 Human,它派生出来三个子类 Chinese 类、American 类和 British 类,三个子类中都重写了父类中的方法 speak():void,在测试类中用静态绑定的方式调用方法 speak()
Chinese c = new Chinese();
c.speak();
American a = new American();
a.speak();
British b = new British();
b.speak();
- 这种调用方式是在代码里指定的,编译时编译器就知道 c 调用的是 Chinese 的 speak(),a 调用的是 American 的 speak()
- 如有一类 Human,它派生出来三个子类 Chinese 类、American 类和 British 类,三个子类中都重写了父类中的方法 speak():void,在测试类中用静态绑定的方式调用方法 speak()
- 动态绑定:在程序运行期间由JVM根据对象的类型自动的判断应该调用哪个方法,也叫做后期绑定
- 例:
- 此时,Human类中随机生成 Chinese 类、American 类和 British 类的对象,编译器不能根据代码直接确定调用哪个类中的 speak()方法,直到运行时才能根据产生的随机数 n 的值来确定 human[i] 到底代表哪一个子类的对象,这样才能最终确定调用的是哪个类中的 speak()方法,这就是动态绑定
向下转型
- 向下转型是与向上转型相对的概念,它是用子类引用指向父类实例
- 如:下图,在进行转换时会报错
- 这时就告诉我们向下转型不能自动转换,我们需要强转,所以向下转型又叫强制类型转换
- 正确的转换语句为:
- 向下转型后,可以调用子类自己独有的方法
- 兄弟类之间不能进行强制类型转换
instanceof运算符
- 基本概念
- instanceof 运算符用来判断对象是否可满足某个特定类型实例特征。返回值为 true/false。一般用于 if 语句中
- 表示方法
- 如:
boolean result;
Pen pc = new Pencil();
result = pc instanceof Pencil;
- 如果左边对象是右边类的实例则返回 true,否则返回 false
- instanceof 运算符的应用
- 用 instanceof 运算符来判断对象是否满足某个特定类型实例特征
- 例:
//对象实例化
Parents f = new Father();
Parents m = new Mother();
//用instanceof运算符判断对象是否满足某个特定对象实例特征
System.out.println(m instanceof Father);
System.out.println(m instanceof Mother);
System.out.println(m instanceof Object);
System.out.println(f instanceof Father);
- 运行结果为:
false
true
true
true
案例总结
public class Animal {
//属性:kind(种类)
private String kind;
public Animal(){
}
//创建带参(king为参数)构造函数
public Animal(String kind) {
}
//应用封装实现对私有属性的get/set操作
public String getKind() {
return kind;
}
public void setKind(String kind) {
this.kind = kind;
}
//创建成员方法cry():void
public void cry() {
}
}
public class Cat extends Animal {
//重写父类cry()方法,输出信息为“小猫的叫声:喵喵喵~~~”
public void cry() {
System.out.println("小猫的叫声:喵喵喵~~~");
}
}
public class Dog extends Animal {
//重写父类cry()方法:输出信息为“小狗的叫声:汪汪汪~~~”
public void cry() {
System.out.println("小狗的叫声:汪汪汪~~~");
}
}
public class Sheep extends Animal {
//重写父类的方法cry(),要求输出信息“小羊的叫声:咩咩咩~~~”
public void cry() {
System.out.println("小羊的叫声:咩咩咩~~~");
}
}
public class Test {
public static void main(String[] args) {
Animal[] n = new Animal[5];
for (int i = 0; i < n.length; i++) {
int temp = (int) (Math.random() * 3);
switch (temp) {
case 0:
n[i] = new Cat();
break;
case 1:
n[i] = new Dog();
break;
case 2:
n[i] = new Sheep();
break;
}
n[i].cry();
}
}
}