向下转型
有了对象的多态性以后,内存上实际上是加载了子类特有的属性和方法的,但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的属性和方法,子类特有的属性和方法不能调用。
如何才能调用子类特有的属性和方法?
向下转型:使用强制类型转换符
注:此处完整代码见JAVA基础(十)
Person p1 = new Man();
Man m1 = (Man)p1;
使用强转时,可能出现ClassCastException的异常
Person p1 = new Man();
Woman m1 = (Woman )p1;
m1.goShoping(); //异常
因为内存中没有Woman的属性和方法
instanceof 操作符
x instanceof A:检验x是否为类A的实例,返回值为boolean型
要求x所属的类与类A必须是子类和父类的关系,否则编译错误。
如果x属于类A的子类B,x instanceof A值也为true。
if (p1 instanceof Person) {
System.out.println("____Person____");
}
if (p1 instanceof Object) {
System.out.println("____Object____");
}
为了避免在向下转型时出现异常,我们在向下转型前,先进行instanceof的判断,一旦返回true,就进行向下转型,否则就不执行向下转型
if (p1 instanceof Woman) {
System.out.println("____Woman____");
Woman w2 = (Woman)p1;
w2.goShopping();
}
if (p1 instanceof Man) {
System.out.println("____Man____");
Man m2 = (Man)p1;
m2.earnMoney();
}
测试代码
package com.xxx.java;
public class PersonTest {
public static void main(String[] args) {
Person p = new Person();
p.eat();
Man m = new Man();
m.eat();
m.age = 25;
m.earnMoney();
System.out.println("*******************");
//多态性
Person p1 = new Man();
Person p2 = new Woman();
p1.eat(); //执行子类重写的方法
p1.walk();
System.out.println(p1.id);
//p1.earnMoney();
System.out.println("**********************");
//Man m1 = (Man)p1;
//m1.earnMoney();
//m1.isSomking = true;
//Woman w1 = (Woman)p1;
//w1.goShopping();
if (p1 instanceof Woman) {
System.out.println("____Woman____");
Woman w2 = (Woman)p1;
w2.goShopping();
}
if (p1 instanceof Man) {
System.out.println("____Man____");
Man m2 = (Man)p1;
m2.earnMoney();
}
if (p1 instanceof Person) {
System.out.println("____Person____");
}
if (p1 instanceof Object) {
System.out.println("____Object____");
}
//练习:编译通过,运行不通过:
//Person p3 = new Person();
//Man m3 = (Man)p3;
//编译通过,运行通过
Object obj = new Woman();
Person p4 =(Person)obj;
//编译不通过
//Man m5 = new Woman();
}
}
练习
package com.xxx.exer;
public class FieldMethodTest {
public static void main(String[] args) {
Sub s = new Sub();
System.out.println(s.count); //20
s.display(); //20
//多态性
Base b = s;
System.out.println(b == s); //true
System.out.println(b.count); //10
//虚拟方法调用
b.display(); //20
}
}
class Base {
int count = 10;
public void display() {
System.out.println(this.count);
}
}
class Sub extends Base {
int count = 20;
public void display() {
System.out.println(this.count);
}
}
子类继承父类
若子类重写了父类方法,就意味着子类里定义的方法彻底覆盖了父类里的同名方法,系统将不可能把父类里的方法转移到子类中。
对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量
练习2
class Person {
protected String name="person";
protected int age=50;
public String getInfo() {
return "Name: "+ name + "\n" +"age: "+ age;
}
}
class Student extends Person {
protected String school="pku";
public String getInfo() {
return "Name: "+ name + "\nage: "+ age + "\nschool: "+ school;
}
}
class Graduate extends Student{
public String major="IT";
public String getInfo() {
return "Name: "+ name + "\nage: "+ age + "\nschool: "+
school+"\nmajor:"+major;
}
}
建立InstanceTest 类,在类中定义方法 method(Person e);
在method中:
(1)根据e的类型调用相应类的getInfo()方法。
(2)根据e的类型执行:
如果e为Person类的对象,输出: “a person”;
如果e为Student类的对象,输出: “a student”
“a person ”
如果e为Graduate类的对象,输出: “a graduated student”
“a student”
“a person”
package com.xxx.exer;
public class InstanceTest {
public static void main(String[] args) {
InstanceTest test = new InstanceTest();
test.methed(new Person());
}
public void methed(Person e) {
System.out.println(e.getInfo());