Simple
回归自我,努力奋斗
posts - 0,comments - 0,trackbacks - 0
    这一段时间在写代码的时候,使用instanceof 关键字比较A类对象是不是B类时,出现了Incompatible conditional operand types A and B错误。当我试图将A类对象强制转换成B类((B)a)时,出现了Cannot cast from A to B错误,让我百般不得其解。进过一段时间的探讨和研究,总算有些体会,下面将逐一道来。先来看看几个关键类的定义:
public class A {
}

public class B {
}

public interface C {
}

public class D implements C {
}

public class Bootstrap {
    
public static void main(String[] args) {
        A a = new A();
//        B b = (B)a; //Error:Cannot cast from A to B
//        if(a instanceof B){ //Error:Incompatible conditional operand types A and B
//        }
        D d = new D();
        
if(d instanceof C){
        }

    }

}
    此例中,我定义了三个类和一个接口,A类与B类互不相关,D类继承了接口C.在测试类中,我首先定义了一个A类对象a。当我试图将对象a强制转换成B时,编译器抛出了Cannot cast from A to B,导致编译无法通过。为什么编译无法通过呢?我考虑的原因是这样的?由于A类与B类毫无继承关系,因此他们没有转换的必要,而且也无法将A类对象转换成B类,因此,java编译器在编译的时候,就进行了检查,如果没有必要转换,就认为是书写错误,不允许编译。这个原理也可应用于instanceof上,本身两个类就毫无继承关系,那么就没有必要判断对象a是不是类B了。
    接着,我定义了D类对象d,使用instanceof关键字判断d是不是C.显然对象d是属于C的,这就好像:造纸厂继承了抽象接口工厂,那么造纸厂当然也是工厂啦。下面,我们来看一下另外一种情况:
public class Bootstrap {
    
public static void main(String[] args) {
        A a = new A();
        
if(a instanceof C){  //编译能通过
        }

        C c = (C)a;
    }

}
    我修改了测试类代码,使用instanceof判断了对象a是不是接口C,编译竟然能通过,为什么呢?明明A类并未继承接口C啊!!我想原因是这样的,对应对象A来说,他有可能是A类本身,也可能时A类的子类(java运行默认向上转型),java编译器并未进一步确定对象A类的具体类型,如果对象a是A类的子类实例的话,那么A类的子类完全有可能继承接口C,因为java类级别是单继承的,而接口级别是多继承的,因此,这种判断就有意义了。这儿也可说明使用instanceof判断A类对象是不是B类时出错,因为java类级别采用单继承,因此A类的子类也不能继承自B,因此他们始终都无法扯上继承关系。同样的原理也用于类型转换上。
    那么instanceof或者转型在哪些地方使用才有意义呢?
    1.A继承B
        当A继承自B时,A类对象a显然是B类,举个简单的例子,Manager类继承Employee类,那么经理类的实例manager当然也是Employee啦,因为即使你是经理,你也是公司的员工.
    2.B继承A
        当B继承自A事,A类对象a有可能是B类,也有可能不是B类。举个例子,当我们这样实例化时A a = new B();那么对象a就是B类型的啦,但当我使用A a = new A()时,a就不是B类型的了。这就好像经理是员工,而员工不一定都是经理一样。
    3.A与接口C
        A直接继承自接口C就不说了,来说一下A不直接继承自接口C。由于A的子类有可能继承自接口C,因此这种判断也就存在意义了。假设我们这样实例化:A a = new E(),其中E是A的子类,而且也继承接口C。那么我们使用 a instanceof C时,就会是true。因为对象a确实是接口C。

    其他情况:
        在泛型中使用instanceof时,会抛出Cannot perform instanceof check against parameterized type List<String>. Use instead its raw form List since generic type information will be erased at runtime错误,字面意思是instanceof关键字不能用于参数化的类型判断,建议使用原生类型。这个可能是java遗留的历史原因,因为在jdk5之前,java中没有泛型概念,而instanceof在以前的版本中已经实现,因此使用该功能对泛型进行判断时,会出现错误.




posted on 2011-08-07 11:30 Mr.simple 阅读(1471) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航: