秦疆的JavaSE课程笔记:72 面向对象 instanceof和类型转换

  • instanceof关键字,用于判断左边的对象是否属于右边的
  • 先创建4个类,父类Person,其子类StudentTeacher,测试类Application。在Application中测试instanceof语句:
//父类
public class Person {}
//子类
public class Teacher extends Person {}
//子类
public class Student extends Person {}
//测试类
import OOP.demo.Person;  
import OOP.demo.Teacher;  
import OOP.demo.Student;  
public class Application {  
    public static void main(String[] args) {  
        Object a = new Student();  
        System.out.println(a instanceof Student);  
        System.out.println(a instanceof Person);  
        System.out.println(a instanceof Object);  
        System.out.println(a instanceof Teacher);  
        System.out.println(a instanceof String);  
    }  
}
====运行结果====
true
true
true
false
false
  • 上述代码存在三条继承关系:

    • Object>Person>Teacher
    • Object>Person>Student
    • Object>String
  • 首先,a本身属于Object引用类型,调用的是Student类的构造器,也就是Student类的实例对象,按照instanceof“判断左边的对象是否属于右边的类”的功能,所以判断的是Student对象(而非Object类)是否属于列举的类,当然,属于父类PersonObject,但不属于TeacherString

  • 其次,a作为一个Object类,是可以强制转换为其他子类,所以编译不会报错。

  • Object a = new Student();改为Person b = new Student(); a替换为b,其余不变。

import OOP.demo.Person;  
import OOP.demo.Teacher;  
import OOP.demo.Student;  
public class Application {  
    public static void main(String[] args) {  
        Person b = new Student();  
        System.out.println(b instanceof Student);  
        System.out.println(b instanceof Person);  
        System.out.println(b instanceof Object);  
        System.out.println(b instanceof Teacher);  
        //System.out.println(b instanceof String);   报错:不可转换的类型
    }  
}
====运行结果====
true
true
true
false
  • 不可转换的原因是,b属于Person引用类型,和String虽然同属Object的子类,但是相互之间没有继承关系,无法转换,故而报错

  • 再将Person b = new Student();改为Student c = new Student(); b替换为c,其余不变。

import OOP.demo.Person;  
import OOP.demo.Teacher;  
import OOP.demo.Student;  
public class Application {  
    public static void main(String[] args) {  
        Student c = new Student();  
        System.out.println(c instanceof Student);  
        System.out.println(c instanceof Person);  
        System.out.println(c instanceof Object);  
        //System.out.println(c instanceof Teacher);   报错:不可转换的类型
        //System.out.println(c instanceof String);   报错:不可转换的类型  
    }  
}
====运行结果====
true
true
true
  • 报错的原因同上。

  • 我自己的小结:

    • X a = new Y();语句,决定了a的引用类型X,和调用的构造器Y(),也就是说,aY类的实例对象。前提是类型X是类型Y的父类或者本身。
    • a instanceof Z语句,是看对象a是否从属于右边的类Z,看的是a调用的构造器Y()所属的类型YZ类型的继承关系。有关则为true,无关则为false。
    • 而报错与否看的是a引用类型XZ类型的继承关系,没有继承关系则无法相互转换,故而报错。(这应该涉及到instanceof关键词的底层原理)
  • 类型转换

//父类
public class Person {
	public void run() {  
	    System.out.println("run");  
	}
}
//子类
public class Student extends Person {
	public void go() {  
		System.out.println("go");  
	}
}
//测试类
import OOP.demo.Person;  
import OOP.demo.Student;  
public class Application {  
    public static void main(String[] args) {  
        Person a = new Student();  
        //a.go();   报错,父类无法调用子类的方法
        //通过强制转换,将父类转换为子类
        Student b = (Student) a;
        b.go();
    }  
}
  • 高转低(父转子),要通过强制转换。

  • 当然,也可以使用((Student) a).go将上述两句合成一句,没有必要再创建一个变量。

  • 沿用上面的代码,在测试类中试验子类转父类。

import OOP.demo.Person;  
import OOP.demo.Student;  
public class Application {  
    public static void main(String[] args) {  
        Student a = new Student();  
        a.go();   //子类调用自己的方法,没有问题
        Person b = a;  //子类转父类自动转换,不需要强制转换
        //b.go();   报错,转换为父类后无法调用子类的方法。
    }  
}
  • 子类转换为父类,可能会丢失子类的方法。

  • 总结:

    • 父类引用指向子类的对象
    • 子类转换为父类(向上转型),不用强制转换
    • 父类转换为子类(向下转型),需要强制转换
    • 方便方法的调用,减少重复的代码
posted @ 2023-12-15 17:20  Acolyte_9527  阅读(5)  评论(0编辑  收藏  举报