2014-11-06 60 views
0

我看到这个代码:接口的类的对象,铸造,异常

interface I{}  

class A implements I{} 

class B extends A{} 

class C extends B{} 

class ABC 
{ 

    public static void main(String args[]) 
    { 
     A a=new A(); 
     B b=new B();    
     a=(B)(I)b; //Line 1 
     b=(B)(I)a; //Line 2 
     a=(I)b;  //Line 3 
     I i=(C)a; //Line 4 
    } 
} 

试图找出

  1. 到即有一个安全的铸造哪种方式,而不编译或运行时错误
  2. 在什么情况下铸件会显示编译时错误
  3. 在什么情况下铸件会显示运行时异常

任何人都可以解释我这3个概念吗?

+0

三年线,它不是*投*引起编译时失败 - 它试图为'A'类型的变量赋予一个编译时类型'I'的值... – 2014-11-06 19:20:50

+1

在第二行中,你有一个不是'B'的对象,并且你试图将其分配给“B”类型的变量。为什么在运行时会这样? – 2014-11-06 19:22:30

+0

因为我们把它铸造成B @ david – Gpar 2014-11-06 19:26:01

回答

0

在java中,与类相似的接口是类型。在你的例子中,A类的对象是A类型的,并且是I类型的.B类型的对象是B类型,A类型(子类型)A和I类型.C类型的对象是C类型的,类型(子类型)B,类型(子类型)A和I类型。注意到,对象是两种类型的类型(两种类型彼此没有链接,即A和I是独立类型)以及它们各自超类的子类型。

根据Leskov的替代原则,您可以取代超类型(超级类别)的子类型(子类)。为了说明看看下面的代码片段:

公共类InheritanceTest {

public interface I{} 
public class A implements I{} 
public class B extends A{} 
public class C extends B{} 
public class D implements I{} 
public class E{} 

public void method(){ 

    A a=new A(); 
    B b=new B(); 
    C c=new C(); 

    D d=new D(); 

    I i=null; 

    i=a;i=b;i=c; 

    a=b; 
    b=c; 
    a=c; 

    a=(A)i;//a=i does not work, A and I are two different types 

    i=d; 
    a=(A)i;//ClassCastException at runtime, D is not an A 

    E e=new E(); 
    //a=(A)e; - this generates a compile time error 

}//method closing 

} //级关闭

演员是必要的,因为,按照代码,所有的作为都是,但所有是不是因为我可以有一个类D实现了我,但完全不连接到A继承层次结构。一般来说,当你必须在两个未连接的类型之间进行转换时,你需要进行转换。

注:我编辑的代码,包括其他类d 注:我已编辑的代码包含另一个E类

+0

最后但是2行你的意思是=(D)我? @Ironlca – Gpar 2014-11-07 09:04:25

+0

@Gpar,我已经稍微编辑了代码,我想强调的是D类型的对象,尽管I型不是A型的(因为A和I是两个独立的类型)。在编译时,这行不会在运行时产生任何错误。 – Ironluca 2014-11-07 09:27:34

+0

我可能有点笨,问这个抱歉,为什么不能编译器看到我= D和D不能是A型,然后显示编译时错误,而不是运行时异常?作为a =(A)d;是一个编译时错误@Ironluca – Gpar 2014-11-07 09:53:12