2013-08-19 57 views
1

当我尝试与Colorable接口指向Car类的对象,而无需使用工具类汽车i未显示任何编译错误(虽然它显示运行时错误)(问题1)和当我尝试对班级做同样的事情,我不会延长车辆等级,并尝试用车辆类别指示车辆的对象,它立即显示编译错误。为什么?接口参考变量

问题1:

interface Colorable {} 

class Vehicle {} 

class Car extends Vehicle {} 

public class Tester { 

    public static void main(String[] args) { 

    Car c=new Car(); 
    Vehicle a = (Vehicle)c; 

    Colorable i = (Colorable)c; 

    System.out.println("Successful"); 
    } 
} 

问题2:

interface Colorable {} 

class Vehicle {} 

class Car {} 

public class Tester { 

    public static void main(String[] args) { 

    Car c=new Car(); 
    Vehicle a = (Vehicle)c; 

    Colorable i = (Colorable)c; 

    System.out.println("Successful"); 
    } 
} 
+4

当您输入问题时,编辑区域旁边有一个方便的** How to Format **框。值得一读。在下面还有一个预览,您可以在其中看到您的问题的样子,以及编辑区域上方的格式化工具栏。由于这不是你的第一个问题,请在发布之前花时间清楚地设置事物的格式,而不是依赖像拉胡尔这样的人为你做。 –

+0

问题2:由于Car没有实现该接口,因此不能将c转换为Colorable(“Colorable i =(Colorable)c;”)。但是,如果您可以向我们显示您引用的错误输出,它会非常有帮助。 – tbsalling

+0

也许你会得到至少一个编译警告有关选中铸件... –

回答

8

这是可能的Car一个子类的实例来实现Colorable,这就是为什么它不是一个编译期时间错误。

然而,在问题2鉴于VehicleCar是完全独立的层次,编译器知道这是不可能的任何Car参考也是的Vehicle实例的引用...所以它可以拒绝编译时间。

基本上,类和接口之间的区别在于接口可以在类型层次结构下面实现,而层次结构中有一个继承链,这意味着编译器可以检测到更多问题。

如果Car被标记为final,编译器将同样能够告诉它的Car一个实例是不可能的,也能实现Colorable,并将是一个编译时错误太多。

+0

但如果你采取下面的示例类可着色{} 类车{} 类汽车整车扩展{} 公共类测试仪{ 公众static void main(String [] args){c0 = new Car(); 车辆a = c; Colorable i = c; System.out.println(“Successful”); } } – user2662247

+0

@ user2662247:那么是什么?你没有说过你会发生什么。 –

+0

在上面的代码中,汽车的子类(例如车辆)也可以继承可着色的类,所以如果我写车辆延伸可着色,那么程序成功执行,但是如果我不延长它在车辆中,如我已经显示上面的例子,那么它是一个编译错误,如果我使可见的接口,而不是类的运行时错误。 – user2662247

2

在编译期间,类层次结构是已知的。 Java立即知道是否Car是-a Vehicle

接口更棘手。考虑以下代码:

interface Colorable {} 

class Vehicle {} 

class Car extends Vehicle implements Colorable {} 

{ 
    // case 1: 
    Vehicle vehicle1 = new Vehicle(); 
    Colorable colorable = vehicle1; // error 

    // case 2: 
    Vehicle vehicle2 = new Car(); 
    Colorable colorable2 = vehicle2; // OK! Car implements Colorable! 
} 

即使一个Vehicle没有实现ColorableVehicle实力的子类。因此运行时不会编译时错误。

+0

您的上面的代码是可以的,因为vehicle2引用变量保存了我正在传递的汽车的引用ID colorable2,它也可以保存汽车变量的参考ID。但在case1中,您正在尝试将车辆类别引用ID分配给可能的着色参考变量,例如。考虑我的下一个评论中给出的代码。 – user2662247

+0

类着色的{} 类车辆延伸着色的{} 类汽车延伸车辆{} 公共类测试仪{ 公共静态无效的主要(字串[] args){ 轿厢C =新车(); 车辆a = c; Colorable i = c; System.out.println(c); System.out.println(a); System.out.println(i); } } – user2662247

0

在第一种情况下

Car c=new Car(); 
Vehicle a = (Vehicle)c; 
Colorable i = (Colorable)c; 

有两两件事 -

  1. 要创建一个Car对象。然后,您使用Vehicle参考指向由于您的Car类扩展Vehicle类而有效的汽车对象。
  2. 然后您使用Colorable参考指向汽车对象。现在有可能某些汽车子类实现Colorable接口。例如

    class myCar extends Vehicle implements Colorable{}

,然后你做

Car c=new myCar(); 
Colorable i = (Colorable)c; 

这不应该抛出运行时异常。在你的情况下,你告诉编译器相信你会有一些可以实现可着色接口的类车子类,但事实并非如此。所以你会得到一个编译时错误,但是当你违反这个信任时,你会得到一个运行时错误。

+0

假设我将界面着色为可着色的类,如果我将该可着色类延伸到车辆类,那么我可以用可着色的参考变量指向该车对象。但是,如果现在不延长可着色到车辆,是一个编译错误..但在接口的情况下它是运行时。 – user2662247