接口引用变量

时间:2013-08-19 12:27:02

标签: java oop inheritance interface

当我尝试使用Car接口指向Colorable类的对象而不使用类car中的implements时,我没有显示任何编译错误(尽管它显示运行时错误)(问题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");
  }
}

3 个答案:

答案 0 :(得分:8)

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

但是,在问题2中,VehicleCar是完全独立的 class 层次结构,编译器知道任何Car引用也不可能对Vehicle的实例的引用...所以它可以在编译时拒绝它。

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

如果Car被标记为final,编译器同样可以告诉Car的实例也无法实现Colorable,并且< em> 也是编译时错误。

答案 1 :(得分:2)

在编译期间已知类层次结构。 Java立即知道Car是否是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的子类也可能。因此运行时没有编译时错误。

答案 2 :(得分:0)

在第一种情况下

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

有两件事 -

  1. 您正在创建一个Car对象。然后,您使用Vehicle引用指向一个有效的汽车对象,因为您的Car类扩展了Vehicle类。
  2. 然后您使用可着色参考指向汽车对象。现在有可能某些子类汽车实现了Colorable接口。例如

    class myCar extends Vehicle implements Colorable{}

  3. 然后你做

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

    这不应该抛出运行时异常。在你的情况下,你告诉编译器相信你会有一些实现Colorable接口的类汽车的子类,但事实并非如此。因此,您将获得编译时错误,但是当您破坏该信任时,您将收到运行时错误。