为什么在这种情况下我需要演员表?

Why do I need cast in this case?

示例:

class AbstractConverter <T> {
   public abstract T convert(AbstractEntity e);
} 

class CityEntity extends AbstractEntity {...}

class CityConverter extends AbstractConverter {
  @Override
  public CityDTO convert(CityEntity entity) {...} // why can't I do that??
}

由于我的 CityEntity 是 AbstractEntity 类型,为什么我不能在我的 cityConverter 中这样做?

  The method convert(CityEntity) of type CityConverter must override or implement a supertype method

我猜解决方案是强制转换,但这并不优雅:

 @Override
public CityDTO convert(AbstractEntity entity) { 
  CityEntity cityEntity = (CityEntity) entity;
}

您的 CityConverter extends AbstractConverterAbstractConverter<T> 需要为

实施
public abstract T convert(AbstractEntity e);

extends AbstractConverter 使用 raw-types 不是问题,因为在返回 object 的情况下覆盖方法可以更具体(因为它仍然是 [=50 描述的类型=] class).

但是当在派生 class 中您需要更具体的类型作为参数时,问题就出现了。

请记住,派生的 class 仍然可以从属于 parent 类型之一的引用中使用,例如可以使用如下代码:

AbstractConverter ac = new CityConverter();

因此,当我们调用 ac.convert(...) 时,编译器将允许我们使用任何类型的 AbstractEntity 作为参数,而不仅仅是 CityEntity 可能会破坏 CityConverter#convert 的代码。

这就是为什么我们在重写方法参数时不能声明更具体类型的方法参数。

现在关于您标题中的问题:

Why do I need cast in this case?
...

CityEntity cityEntity = (CityEntity) entity;

你需要强制转换,因为 entity 被声明为 AbstractEntity 这意味着传递的实例有可能不是 CityEntity 类型,因此编译器无法编译代码:

CityEntity cityEntity = entity;//error without cast

通过转换你基本上是在说 "I am sure that passed instance will be of type (CityEntity) and if not, I am willing to face consequences and am ready to see my application stopped by ClassCastException"。

您不能减少允许的参数类型,因为这样会破坏 Liskov substitution principle。如果一个人在一个未知的 AbstractConverter 实现上调用 convert(由于多态性),他会猜测他总是可以传递任何 AbstractEntity 实现。如果 CityConverter 只允许非常特定的子类型,则情况并非如此。

现在关于您的代码:

class AbstractConverter <T> {
   public abstract T convert(AbstractEntity e);
}

这里首先让我疑惑的是:为什么AbstractEntity这里是固定类型?如果我总是想将 AbstractEntity 实例转换成不同的东西,我会将转换器命名为 class AbstractEntityConverter 或类似的名称。

所以我猜你真的想要这样的东西:

class AbstractConverter<F, T> {
   public abstract T convert(F source);
}

其中 F 是作为源的 "from" 类型, T 是将返回的目标类型。所以你可以让 AbstractConverter 子类型决定他们喜欢转换什么。

那么你有这个:

class CityConverter extends AbstractConverter {
}

这里为什么用AbstractConverter作为raw type?不应该吗?

class CityConverter extends AbstractConverter<CityDTO> {
}

但无论如何,如果你喜欢使用我的建议,那么还要添加源类型:

class CityConverter extends AbstractConverter<CityEntity, CityDTO> {
    @Override
    public CityDTO convert(CityEntity entity) {...}
}

这行得通。