Java继承转换运行时错误与编译器错误 问题

Java继承转换运行时错误与编译器错误 问题,java,inheritance,casting,compiler-errors,runtime-error,Java,Inheritance,Casting,Compiler Errors,Runtime Error,考虑下面的代码B继承自A,并且没有一个继承自String 我想知道以下问题的答案: 为什么第一个演员是B b1=(B)a1,是否生成运行时错误 为什么第一个第二个演员是,stringb1=(String)a1,是否生成编译错误 为什么会有区别?为什么编译器在第一种情况下看不到问题 代码 类A: public class A {} 和类B: public class B extends A {} 为什么第一个演员B b1=(B)a1;,是否产生运行时错误 A类型的变量可以存储B的实例。但是

考虑下面的代码
B
继承自
A
,并且没有一个继承自
String

我想知道以下问题的答案:

  • 为什么第一个演员是B b1=(B)a1,是否生成运行时错误
  • 为什么第一个第二个演员是,
    stringb1=(String)a1,是否生成编译错误
  • 为什么会有区别?为什么编译器在第一种情况下看不到问题
  • 代码 类
    A

    public class A {}
    
    
    和类
    B

    public class B extends A {}
    
    
  • 为什么第一个演员B b1=(B)a1;,是否产生运行时错误
  • A
    类型的变量可以存储
    B
    的实例。但是,并非所有
    A
    的实例都是
    B
    的实例

    A
    不是
    B
    ,而是
    B
    A
    。(比如,并非所有动物都是狗,但狗是动物)

  • 为什么第一个第二个字符串b1=(字符串)a1;,是否产生编译错误
  • A
    不是
    String
    的超类型,
    String
    也不是
    B
    的超类型

  • 为什么会有区别?为什么编译器在第一种情况下看不到问题
  • 因为
    A
    类型的变量可以存储
    B
    的实例;但是
    A
    类型的变量永远不能存储
    String
    的实例

  • 为什么第一个演员B b1=(B)a1;,是否产生运行时错误
  • A
    类型的变量可以存储
    B
    的实例。但是,并非所有
    A
    的实例都是
    B
    的实例

    A
    不是
    B
    ,而是
    B
    A
    。(比如,并非所有动物都是狗,但狗是动物)

  • 为什么第一个第二个字符串b1=(字符串)a1;,是否产生编译错误
  • A
    不是
    String
    的超类型,
    String
    也不是
    B
    的超类型

  • 为什么会有区别?为什么编译器在第一种情况下看不到问题

  • 因为
    A
    类型的变量可以存储
    B
    的实例;但是
    A
    类型的变量永远不能存储
    String

    类型
    A
    的变量实际上可以是
    B
    类型,因为B扩展了A。但是
    A
    类型的变量永远不能是
    String
    类型。这就是为什么编译器可以捕获对
    String
    的转换,但不能捕获对
    B
    的转换类型
    A
    的变量实际上可以是
    B
    类型,因为B扩展了A。但是
    A
    类型的变量永远不能是
    String
    类型。这就是为什么编译器可以捕捉到对
    字符串的转换,但不能捕捉到对
    B
    的转换

    为什么第一个演员B b1=(B)a1;,是否产生运行时错误

    因为
    a1
    A
    的实例,但与
    B
    不兼容。具体来说,
    newa()
    创建的对象与
    A
    的子类不兼容。如果对象的运行时类(即调用
    new
    的类)与目标类不同或不是目标类的子类,则在运行时转换到该目标类将失败。这仅仅是因为子类与该对象无关

    为什么第一个第二个字符串b1=(字符串)a1;,是否产生编译错误

    即使实际的强制转换发生在运行时,编译器也会执行类型检查并防止像这样的无意义操作。在这种情况下,将
    A
    对象强制转换为
    String
    是毫无意义的,编译器可以检测到它:
    String
    A
    之间没有关系,编译器知道哪个类是其他类的子类。编译器知道在Java中,
    a1
    不能成为
    String
    String
    的子类的实例,这是因为
    String
    不是
    a
    的父类,后者是
    a1
    的声明类型。也有例外情况,例如当开始对接口进行转换时

    为什么会有区别?为什么编译器在第一种情况下看不到问题

    编译器仅基于静态类型(变量或表达式的类型)验证类型强制转换。它不查看runtime类,当然,在运行时实际创建对象之前,runtime类是不可用的。当它能够确定强制转换不可能有效时(例如在第二种情况下),它将失败。在第一种情况下,从
    A
    转换到
    B
    可以通过编译,因为声明的类型是兼容的(即
    A
    对象可能是
    B
    的实例,编译器将其留给运行时检查实际对象)。在第二种情况下,编译器知道
    A
    对象永远不能是
    String
    的实例(因为
    String
    不在
    A
    的类型层次结构中,这在运行时不会改变)

    为什么第一个演员B b1=(B)a1;,是否产生运行时错误

    因为
    a1
    A
    的实例,但与
    B
    不兼容。具体来说,
    newa()
    创建的对象与
    A
    的子类不兼容。如果对象的运行时类(即调用
    new
    的类)与目标类不同或不是目标类的子类,则在运行时转换到该目标类将失败。这仅仅是因为子类与该对象无关

    为什么第一个第二个字符串b1=(字符串)a1;,是否产生编译错误

    即使实际演员
    public class B extends A {}