疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

Java学习笔记instanceof与向下转型


 

 
先来看下instanceof与向下转型的概念:
 
1.instanceof
 
    instanceof是一个二元操作符,用法是:boolean result = a instanceof ClassA,即判断对象a是否是类ClassA的实例,如果是的话,则返回true,否则返回false。
 
 
 
2.向下转型
 
    对于向上转型,笔记12已经说明过了,即父类对象引用指向了子类对象;向下转型是指,子类的对象引用被赋值为父类对象引用,并且赋值时要进行显式的强制类型转换,而该父类对象引用必须是指向子类对象的;向下转型最终还是子类对象引用指向了子类对象,也就是说,向上转型后,再通过向下转型变回来;向上转型后丢失的属性和方法经过向下转型又可见了。关于向下转型的意义,请参考http://blog.csdn.net/xyh269/article/details/52231944。
 
    用文字描述起来比较绕口,看下面的式子就好理解了。记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是子类引用,而子类的属性数及方法数是大于父类的,所以是没法转换为子类对象的。
 
    参考下面的内存图就比较直观了:
 
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;
        DustMan dus = new DustMan();
        
        per2 = stu;
        stu2 = (Student) per2;
//        stu2 = (Student) per;
//        stu2 = (Student) dus;
        
        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判定它既是父类的实例也是子类的实例;即,可以看成子类实例包含了一个父类实例。