感冒咳嗽停更了几天,今天恢复更新了。

先来看下instanceof与向下转型的概念:

1.instanceof

    instanceof是一个二元操作符,用法是:boolean result = a instanceof ClassA,即判断对象a是否是类ClassA的实例,如果是的话,则返回true,否则返回false。

 

2.向下转型

    对于向上转型,笔记12已经说明过了,即父类对象引用指向了子类对象;向下转型是指,子类的对象引用被赋值为父类对象引用,并且赋值时要进行显式的强制类型转换,而该父类对象引用必须是指向子类对象的;向下转型最终还是子类对象引用指向了子类对象,也就是说,向上转型后,再通过向下转型变回来;向上转型后丢失的属性和方法经过向下转型又可见了。关于向下转型的意义,请参考。

    用文字描述起来比较绕口,看下面的式子就好理解了。记Person为父类,Student为子类。

    Person per = new Student(); //向上转型

    Student stu = (Student) per; //向下转型

    由于per本来指向的就是子类对象,所以可以通过显式的类型转换使stu也指向该子类对象。

 

    对于下面的语句,则不能进行向下转型:

    Person per1 = new Person();

    Student stu1 = (Student) per1;

    会出现下面的错误:

    Exception in thread "main" java.lang.ClassCastException: human.Person cannot be cast to human.Student
    at human.TestMain.main(TestMain.java:15)

    因为per1指向的是父类对象,stu1是子类引用,而子类的属性数及方法数是大于父类的,所以是没法转换为子类对象的。

    参考下面的内存图就比较直观了:

java 对象向下转型 底层原理 java向下转型注意_System

 

3.那么怎么判断能不能向下转型呢?

可以先用instanceof判断父类的对象引用是不是指向了子类的实例,是的话,则可以向下转型,否则就不可以。

 

作者: 蝉蝉

请尊重作者劳动成果,转载请在标题注明“转载”字样,并标明原文链接:

 

 

4.下面是例子,代码如下:

package human;

public class TestMain {
    public static void main(String[] args) {
        
        Person per = new Person();
        Person per2;
        Student stu = new Student();
        Student stu2;
        
        per2 = stu;
        stu2 = (Student) per2;
//        stu2 = (Student) per;
        
        if( per2 instanceof Student )
            System.out.println("per2指向的是Student类的对象");
        else
            System.out.println("per2指向的不是Student类的对象");
        if( per2 instanceof Person )
            System.out.println("per2指向的是Person类的对象");
        else
            System.out.println("per2指向的不是Person类的对象");
        
        if( per instanceof Student)
            System.out.println("per指向的是Student类的对象");
        else
            System.out.println("per指向的不是Student类的对象");
        if( per instanceof Person )
            System.out.println("per指向的是Person类的对象");
        else
            System.out.println("per指向的不是Person类的对象");
        
        
        if( stu2 instanceof Student )
            System.out.println("stu2指向的是Student类的对象");
        else
            System.out.println("stu2指向的不是Student类的对象");
        if( stu2 instanceof Person )
            System.out.println("stu2指向的是Person类的对象");
        else
            System.out.println("stu2指向的不是Person类的对象");
        
        if( stu instanceof Student )
            System.out.println("stu指向的是Student类的对象");
        else
            System.out.println("stu指向的不是Student类的对象");
        if( stu instanceof Person )
            System.out.println("stu指向的是Person类的对象");
        else
            System.out.println("stu指向的不是Person类的对象");
    }

}

输出结果如下:

1 per2指向的是Student类的对象
2 per2指向的是Person类的对象
3 per指向的不是Student类的对象
4 per指向的是Person类的对象
5 stu2指向的是Student类的对象
6 stu2指向的是Person类的对象
7 stu指向的是Student类的对象
8 stu指向的是Person类的对象

结果分析:

(1).per2 = stu;

     stu2 = (Student) per2;

per2与stu指向了同一子类对象,所以可以进行向下转型。

(2).// stu2 = (Student) per;

由于per指向的是Person类的对象,所以向下转型会出错。

(3).从1,2,5,6,7,8行输出可以看出,使用instanceof时,不论a定义为父类的对象引用还是子类的对象引用,只要最终指向的是子类对象,instanceof判定它既是父类的实例也是子类的实例即,可以看成子类实例包含了一个父类实例。