类投射异常与“无法投射”编译错误

为我的OCA Java SE 7程序员I考试学习,所以新手问题。我有一个我不明白的例子问题。下面的代码进行编译,但在运行时给出一个 ClassCastException:

interface Roamable {
}

class Phone {
}

public class Tablet extends Phone implements Roamable {
    public static void main(String... args) {
        Roamable var = (Roamable) new Phone();
    }
}

当我切换到我立即得到一个编译错误。Roamable var = (Roamable) new Phone();Roamable var = (Roamable) new String();

两个问题:

  1. 为什么上面的代码会编译呢?手机似乎与我无关 可漫游?
  2. 为什么代码使用 编译,但不使用 ?new Phone()new String()

答案 1

为什么上面的代码会编译呢?手机似乎与我无关 可漫游?

是的,因为它是一个接口,它可能会导致运行时异常,但不会导致编译时异常,因为即使不实现,也可能是的子类,因此编译器没有办法知道它,只能在运行时。RoamablePhoneRoamablePhone

它已经在java语言规范中定义。在这里查看我的答案

为什么代码使用新的 Phone() 进行编译,但不能使用新的 String() 进行编译?

因为 被声明为在包中。如 jls 8.1.1.2 final 类部分中所指定:声明为无法扩展的类,因此它没有任何子类。因此,编译器已经知道无法扩展:因此没有子类的存在可以实现接口。class Stringpublic final classjava.langfinalString Roamable

编辑:(回复您下面的评论)

让我们假设这是一个子类,它实现了一个接口。BAT

现在一个语句:

   T t = (T)new A();

本质上与:

   A aObj = new A() ;
   T t = (T)aObj ; // a run-time exception happen

在得出结论之前,让我们对对象做同样的事情:B

   A aObj = new B();
   T t = (T)aObj; // no exception happen.

所以,这里超类和子类的真正原因是参考。第二个代码示例中的类也是类的实例,但它也是已实现 的类的实例。aObjABT


答案 2

字符串是最终的,因此无法将其转换为可漫游。


推荐