package com.byxy;
public class Person {
private String name;
private int age;
private char gender;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
public Person() {
super();
// TODO Auto-generated constructor stub
}
public Person(String name, int age, char gender) {
super();
this.name = name;
this.age = age;
this.gender = gender;
}
public void print() {
System.out.print("我是"+name+"我年龄是"+age+"岁,我性别是:"+gender);
}
public void learn() {
}
}
package com.byxy;
public class Teacher extends Person{
private String majorField;
public String getMajorField() {
return majorField;
}
public void setMajorField(String majorField) {
this.majorField = majorField;
}
public Teacher() {
super();
// TODO Auto-generated constructor stub
}
public Teacher(String name, int age, char gender) {
super(name, age, gender);
// TODO Auto-generated constructor stub
}
public Teacher(String majorField) {
super();
this.majorField = majorField;
}
@Override
public void print() {
// TODO Auto-generated method stub
super.print();
System.out.println("执行Teacher类中的print方法");
}
}
package com.byxy;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Person p=new Teacher();
p.print();
//p.setMajorField("java");//错误,p对象没有这个方法
// 执行Teacher类中的print()方法
// 从执行结果可以看出,p对象执行的print()方法
// 实际上是Teacher类的print()方法,这一点很重要。
// 要记清楚声明部分为父类,赋值部分为子类的这个对象p,
// 在调用重写的方法时,是调用的子类的方法(指继承而来的方法)。
// 另外,p 对象不存在子类的其他方法,比如p对象
// 没有Teacher类的setMajorField(String majorField)等方法
//强制父类向下转换为子类
//将p强制向下转换并赋值给t
Teacher t=(Teacher)p;
t.setMajorField("java");
}
}
输出结果:
我是周杰伦,我的年龄是30岁,我的性别是男,我的授课方向是Java
从执行结果可以看出,p对象被强制转换为了Teacher并赋值给对象t,t对象具备setMajorField()方法,
因此完成了对属性majorField的赋值,并输出正确结果。
在Java中子类转型成父类是向上转型反过来说收类转型成子类就是向下转型,向下转型必须确定是该类型,
比如代码4-13中的p确实是Teacher类对象,假如现在要把p对象强制转换为Student对象,如图4-1所示,程序会出错。
增加了第14~18行代码后,程序运行出错。因为p不是Student对象,所以转换出错。
2. instanceof运算符
在代码4-13中进行向下转型时,如果没有转换为真实子类类型,就会出现类型转换异常。
如何有效避免出现这种异常呢?Java提供了instanceof运算符来进行类型的判断。其语法如下。
对象instanceof类或接口
该运算符用来判断一个对象是否属于一个类或者实现了一个接口,结果为true或false。
在强制类型转换之前通过instanceof运算符检查对象的真实类型,然后在进行相应的强制类型转换,
这样就可以避免类型转换异常,从而提高代码健壮性。
修改代码4-13得到代码4-14。
package com.byxy;
public class Test1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Person p=new Teacher();
p.setName("周杰伦");
p.setAge(30);
p.setGender('男');
if(p instanceof Teacher) {
//强制父类向下转换为子类
Teacher t=(Teacher)p;
t.setMajorField("java");
t.print();
}else if(p instanceof Student){
//强制将p向下转换为Student对象
Student s=(Student)p;
//s.setGrade("大二");
s.print();
}
}
}
▲ 通过该示例可以发现,在进行引用类型转换时,首先通过instanceof运算符进行类型判断,然后进行相应的强制类型转换,这样可以有效地避免出现类型转换异常。 ▲ 使用instanceof时,对象的类型必须和instanceof的第二个参数所指定的类或接口在继承树上有上下级关系,否则会出现编译错误。例如: pet instanceof String, 会出现编译错误。