以下代码编译并正常工作。我定义了一个 Builder 接口,然后 CarBuilder 类用于处理与 Car 相关的任何事情,而 BusBuilder 类用于处理与 Bus 相关的任何事情。Car 和 Bus 共享一个名为 Vehicle 的抽象类。代码很简单。代码将输出:
do something to CREATE the Car
do something to UPDATE the Car
do something to CREATE the Bus
do something to UPDATE the Bus
这是编译的原始代码:
public abstract class Vehicle { }
public class Car extends Vehicle { }
public class Bus extends Vehicle { }
public interface Builder<V extends Vehicle> {
public V createVehicle(String spec);
public void updateVehicle(String spec, Vehicle vehicle);
}
public class CarBuilder implements Builder<Car> {
public Car createVehicle(String spec) {
Car car = new Car();
System.out.println("do something to CREATE the Car");
return car;
}
public void updateVehicle(String spec, Vehicle vehicle) {
Car car = (Car) vehicle;
System.out.println("do something to UPDATE the Car");
return;
}
}
public class BusBuilder implements Builder<Bus> {
public Bus createVehicle(String spec) {
Bus bus = new Bus();
System.out.println("do something to CREATE the Bus");
return bus;
}
public void updateVehicle(String spec, Vehicle vehicle) {
Bus bus = (Bus) vehicle;
System.out.println("do something to UPDATE the Bus");
return;
}
}
@Test
public void main() {
Builder<? extends Vehicle> builder = null;
Vehicle vehicle = null;
builder = new CarBuilder();
vehicle = builder.createVehicle("my original Car spec");
builder.updateVehicle("my modified Car spec", vehicle);
builder = new BusBuilder();
vehicle = builder.createVehicle("my original Bus spec");
builder.updateVehicle("my modified Bus spec", vehicle);
}
但是,我想让我的代码更加强类型。我想改变接口方法,
从
public void updateVehicle(String spec, Vehicle vehicle);
至
public void updateVehicle(String spec, V vehicle);
换句话说,我尝试在我的接口签名中使用泛型V
而不是基类。Vehicle
这迫使 的实现者Builder
“关闭”特定的产品类型(即Car
or Bus
,但不是基类Vehicle
)。 CarBuilder
只应处理一个Car
;BusBuilder
应该只处理一个Bus
.
代码变成如下:
public interface Builder<V extends Vehicle> {
public V createVehicle(String spec);
public void updateVehicle(String spec, V vehicle);
}
public class CarBuilder implements Builder<Car> {
public Car createVehicle(String spec) {
Car car = new Car();
System.out.println("do something to CREATE the Car");
return car;
}
public void updateVehicle(String spec, Car car) {
System.out.println("do something to UPDATE the Car");
return;
}
}
public class BusBuilder implements Builder<Bus> {
public Bus createVehicle(String spec) {
Bus bus = new Bus();
System.out.println("do something to CREATE the Bus");
return bus;
}
public void updateVehicle(String spec, Bus bus) {
System.out.println("do something to UPDATE the Bus");
return;
}
}
@Test
public void main() {
Builder<? extends Vehicle> builder = null;
Vehicle vehicle = null;
builder = new CarBuilder();
vehicle = builder.createVehicle("my original Car spec");
builder.updateVehicle("my modified Car spec", vehicle); <== compilation error
builder = new BusBuilder();
vehicle = builder.createVehicle("my original Bus spec");
builder.updateVehicle("my modified Bus spec", vehicle); <== compilation error
}
两个编译错误 - Java 编译器不允许这样做,因为“ Builder 类型中的方法 updateVehicle(String, capture#3-of ? extends Vehicle) 不适用于参数 (String, Vehicle) ”。
在Java中有没有办法做我想要完成的事情?在 C# 中,我可以简单地使用var关键字键入我的变量,例如var vehicle
代替Vehicle vehicle
. 我听说 Java 泛型调用是编译时的决定。有什么技术可以克服吗?