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

时间:2017-10-24 20:20:42

标签: java generics polymorphism

我在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自动完成告诉我,validate应该采用ParentThing参数,但是如果我传递ParentThing,编译器仍会抱怨。 :(

如果我投射或删除泛型,这将有效,但我想知道如何做到这一点&#34;对&#34;没有编译器警告的方式。

1 个答案:

答案 0 :(得分:1)

这实际上是您希望从编译器中获得的行为。

您提供的代码实际上并不是类型安全的,因此编译器需要您进行类型转换才有意义。

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

更一般地说,编译器无法保证传递给ParentThing的{​​{1}}实际上可以作为validate的特定子类型进行分配。

由于这个原因,您实际上会发现代码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 } 的类。正如您所指出的,另一个选择是使用typcast。