gpt4 book ai didi

java - 我们可以使用泛型参数动态调用 Java 接口(interface)方法吗?

转载 作者:搜寻专家 更新时间:2023-10-31 19:56:13 25 4
gpt4 key购买 nike

以下代码可以编译并正常工作。我定义了一个Builder接口(interface),然后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);
}

但是,我想让我的代码更加强类型化。我想改变接口(interface)方法,

来自

public void updateVehicle(String spec, Vehicle vehicle);

public void updateVehicle(String spec, V vehicle);

换句话说,我试图在我的接口(interface)签名中使用通用 V 而不是基类 Vehicle。这迫使 Builder 的实现者“关闭”特定产品类型(即 CarBus,但基类 车辆)。 CarBuilder 应该只处理一个CarBusBuilder 应该只处理一个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 泛型调用是编译时决定的。有没有一种技术可以克服这个问题?

最佳答案

有一个成语,叫a capture helper,这有助于在这种情况下。

本质上,根据您对 builder 的声明,编译器只知道 vehicleVehicle 的扩展。此外,它知道 Builder 需要将某种特定类型的 Vehicle 传递给它的 updateVehicle() 方法。编译器无法得出对我们来说显而易见的推断——类型是兼容的。为此,我们必须使用辅助方法来摆脱通配符。

从简单的测试工具来看,实际代码的实际应用并不明显。但是,在这种情况下应用它看起来像下面这样。希望这个示例足以说明这个想法并帮助您将其应用到实际代码中。

public void main()
{
Builder<? extends Vehicle> builder;
Vehicle vehicle;

builder = new CarBuilder();
vehicle = createAndUpdateHelper(builder, "my original Car spec", "my modified Car spec");

builder = new BusBuilder();
vehicle = createAndUpdateHelper(builder, "my original Bus spec", "my modified Bus spec");
}

private static <V extends Vehicle> V createAndUpdateHelper(Builder<V> builder, String s1, String s2)
{
V v = builder.createVehicle(s1);
builder.updateVehicle(s2, v);
return v;
}

关于java - 我们可以使用泛型参数动态调用 Java 接口(interface)方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16657195/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com