有人可以解释这里发生了什么吗?
假设Car
和Bike
是Vehicle
的子类。
我认为Vehicle v
引用会被转换为Bike
。我知道这是非法的,实际上编译器会吐出... Car cannot be cast to Bike
。
但是,Vehicle
不应该被强制转换为Bike
吗?毕竟,Vehicle v
是Vehicle
引用。
public class Test {
public static void main(String[] args) {
Vehicle v = new Car();
Bike b = (Bike) v;
// some stuff
}
}
答案 0 :(得分:3)
错误消息显示Car
,因为这是运行时异常。由于此时它知道Vehicle引用指向的实际实例(Car,Bike或Vehicle),因此它提供了更具体的错误消息。
如果在编译时这是一个异常,编译器会提到Vehicle
,因为编译器可能不知道Vehicle引用指向的实际实例。
答案 1 :(得分:1)
它实际上是一个Car
。 v
的类型为Vehicle
,因此Vehicle v = new Car();
的分配有效,因为Car
为Vehicle
。
对象v
保留其身份;那是一个Car
。因此非法演员阵容从Car
到Bike
。
答案 2 :(得分:0)
该行
Bike b = (Bike) v;
如果v
是传入的Vehicle
,那么将是合法的。所以我猜这个验证是在优化过程中发生的。如果可以的话,编译器想要优化掉正常的工作 - 甚至可能完全优化b
- 当然,如果v
被创建为{{>},可以 {1}}位于上一行,而不是Bike
。
答案 3 :(得分:0)
(半)普通英语回复:
汽车不能突然“变成”自行车或被视为自行车,因为自行车会有不同的属性(变量)描述它,以及交互的不同方式用它(方法)。
然而,它们都是车辆,因此它们会有一些共同点,例如,能够转向,向左或向右转,或换档。
当你有这样的逻辑时,这很简单:
ArrayList<Vehicle> vehicles = new ArrayList<Vehicle>();
vehicles.add(new Bike());
vehicles.add(new Car());
vehicles.add(new Bike());
//Some other crazy code
for(Vehicle v : vehicles) {
v.applyBrakes();
v.changeDownGear();
v.turnRight();
}
Vehicle(Bike,Car,Segway等)的每个子类都有自己的方法实现并适当处理自己
答案 4 :(得分:0)
如果没有源代码,就无法明确地说出什么是合法的,什么不是。但是,可以安全地假设这些类的继承树看起来像
Vehicle | __________ | | Car Bike
Car
和Bike
是Vehicle
的子类,这意味着Vehicle
是Car
和Bike
的推广。在Java中,您可以将子类的实例强制转换为其基类。因此,在这种情况下,您可以将Car
投射到车辆上并像对待实际拥有Vehicle
对象的实例一样对待它。 Bike
也是如此。但是,因为Car
不是Bike
的子类,所以不能从一个转换为另一个。所有Cars
都是Vehicles
,但并非所有Vehicles
都是Cars
。它们也不是Bikes
。 Car
永远不是Bike
,反之亦然。
您这样做是为了创建更具可扩展性的代码。例如,您可以编写能够理解如何与将来编写的代码进行交互的代码。一个例子是一些通用接口,例如drive()
,允许其他开发人员稍后提供自定义实现。你的代码虽然事先编写,但仍可以使用它,因为它可以将新的子类视为基类的实例。