调用在 java 中使用泛型的多态方法



我在Java泛型地狱!正确的方法是什么:

interface Validator<T extends ParentThing> {
  void validate(T item);
}
class ValidatorImplOne implements Validator<ChildThingOne> {
  @Override
  public void validate(ChildThingOne thing1) {
    // whatever
  }
}
class ValidatorImplTwo implements Validator<ChildThingTwo> {
  @Override
  public void validate(ChildThingTwo thing2) {
    // whatever
  }
}
// Initialize this with string to ValidatorImplOne or ValidatorImplTwo instances
Map<String, Validator<? extends ParentThing>> VALIDATORS = ... 
public static void validate(String s, ParentThing thing) {
  Validator<? extends ParentThing> validator = VALIDATORS.get(s);
  // Does not compile! Complains that thing is not the right type.
  validator.validate(thing);
}

甚至Eclipse自动完成功能也告诉我,验证应该采用ParentThing参数,但是如果我传递了ParentThing,编译器仍然会抱怨:(。

如果我强制转换或删除泛型,这将起作用,但我想知道如何在没有编译器警告的情况下以"正确"的方式执行此操作。

这实际上是您希望编译器的行为。

您提供的代码实际上不是类型安全的,因此编译器要求您进行类型转换是有道理的。

这是因为您的每个validate方法实际上都采用 ParentThing 的特定子类。例如,在ChildThingOne验证程序中,传递给验证方法的对象必须可从ChildThingOne 分配。当你有一个 Validator<? extends ParentThing> 的实例时,编译器不知道validate期望的实际类型。

更一般地说,编译器无法保证传递给validateParentThing实际上可分配为 ParentThing 的特定子类型。

由于这个原因,您实际上会发现代码validator.validate(new ChildThingOne())具有相同的编译器错误。

这可以在一个基于您的简单示例中看到:

static class ParentThing {
}
static class ChildThingOne extends ParentThing{
}
interface Validator<T extends ParentThing> {
    void validate(T item);
}
static class ValidatorImplOne implements Validator<ChildThingOne> {
    @Override
    public void validate(ChildThingOne thing1) {
        // whatever
    }
}

public static void validate(String s, ParentThing thing) {
    Validator<? extends ParentThing> validator = new ValidatorImplOne(); //? extends ParentThing means an unknown, but SPECIFIC, implementation of ParentThing
    validator.validate(new ChildThingOne()); //cannot compile
    //The compiler doesn't know if ChildThingOne is the actual type validator wants
}

为了使用泛型执行此操作,您必须使用扩展Validator<ParentThing>的类。 正如您所指出的,另一种选择是使用类型转换。

最新更新