Java 接口类对象、强制转换、异常

Java 接口类对象、强制转换、异常,java,object,interface,casting,Java,Object,Interface,Casting,我看到了这个代码: 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

我看到了这个代码:

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
    }
}
试图找出

  • 哪种方法可以实现安全强制转换,即没有编译时或运行时错误
  • 在什么情况下,强制转换将显示编译时错误
  • 在什么情况下强制转换将显示运行时异常

  • 有人能给我解释一下这三个概念吗?

    在java中,类似于类的接口是一种类型。在您的示例中,类A的对象属于类型A和类型I。类B的对象属于类型B、类型(子类型)A和类型I。类C的对象属于类型C、类型(子类型)B、类型(子类型)A和类型I。如前所述,对象属于两种类型的类型(两种类型之间没有链接,即A和I是独立的类型)以及它们各自超类的子类型

    根据Leskov的替换原理,可以用子类型(子类)代替超类型(超类)。要进行说明,请查看下面的代码片段:

    公共类继承测试{

    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
    
    }//下课

    强制转换是必要的,因为根据代码,一切照旧,但一切都不照旧,即我可以有一个实现了i但与a继承层次结构完全无关的类D。通常,当您必须在两个未连接的类型之间转换时,需要强制转换

    注意:我已经编辑了代码以包含另一个D类
    注意:我对代码进行了编辑,为第三行添加了另一个类E

    ,导致编译时失败的不是强制转换-而是试图将编译时类型
    I
    的值分配给
    a
    类型的变量……在第2行,您得到了一个不是
    B
    的对象,您试图将其分配给类型为
    B
    的变量。为什么这在运行时是可以的?因为我们已经将其铸造到B@davidI,但您不知道铸造是什么。这不是一种将对象从一个类转换为另一个类的方法。它不会改变底层对象。最后两行是指a=(D)i吗@Ironlca@Gpar,我稍微编辑了代码,我想强调的是类型D的对象,虽然类型I的对象不是类型A的对象(因为A和I是两个独立的类型)。在编译时,这一行不会在运行时产生任何错误。我可能会有点愚蠢地问这个问题。对不起,为什么编译器不能看到I=d,d不能是A类型,然后显示编译时错误而不是运行时异常?作为a=(a)d;是一个编译时错误@Ironluca@Gpar,这是一个自然的问题。首先,类A的对象属于类型I。其次,Java是一种强类型语言,它检查对象的类型分配,现在,这种类型检查对可用的编译时信息进行操作,例如变量(符号)I属于类型I,变量A属于类型A,A的对象也属于类型I,因此允许强制转换,编译器通常无法确定实际分配给i的是什么,这是一个运行时问题,因此它不会在a=(a)i上生成任何错误。。。续。最后一行(注释),编译时知道a和e不是同一类型,因此生成编译时错误,在这种情况下不需要运行时信息来确定是否存在错误。这也是a=i赋值不起作用的原因,它们是两种不同的类型,需要强制转换。因此,编译器会突出显示任何可能由编译时信息确定的错误,并且需要运行时信息,编译器不会生成错误