Java:如何覆盖这种通用方法?
public List save(Iterable entities) { //... }
如果我使用以下方法来覆盖
@Override public List save(Iterable structures) { List result = new ArrayList(); //... return result; }
我收到以下错误:
method does not override or implement a method from a supertype name clash: save(Iterable) in MyTypeRepositoryImpl and save(Iterable) in SimpleJpaRepository have the same erasure, yet neither overrides the other where S,T are type-variables: S extends T declared in method save(Iterable) T extends Object declared in class SimpleJpaRepository
我怎么解决这个问题? 我不需要该方法是通用的,事实上它不应该是。 我的意思是
@Override public List save(Iterable structures) { List result = new ArrayList(); //... return result; }
无法工作,因为该方法可以创建一个新的MyType对象,它不与List“兼容”。
我怎样才能做到这一点?
编辑:
为了澄清。 我正在尝试覆盖Spring数据SimpleJpaRepository的不同save()方法(由QuerydslJpaRepository扩展)
课程定义:
public class MyTypeRepositoryImpl extends QueryDslJpaRepository implements MyTypeRepository @NoRepositoryBean public interface MyTypeRepository extends JpaRepository, QueryDslPredicateExecutor
而这(来自Spring Data)
public class QueryDslJpaRepository extends SimpleJpaRepository implements QueryDslPredicateExecutor
编辑2:
该方法为每个元素调用save(MyType实体),该方法包含以下逻辑:
- entity有一个独特的字段
- 获取该字段值并检查具有该值的实体是否已存在
- 如果是,则使用该实体(调用entityManager.merge) – >不起作用返回MyType而不是S.
- 如果没有创建新的 – >这里创建了新对象。 不适用于generics类型
对于4.我可以设置id = null并使用传入的对象。 这不适用于3。
所以我很困惑为什么这个方法有这个签名。 它使我无法使用它,我不知道为什么我会使用Ts DAO保存T的子类。 保存方法是唯一的。 所有其他人只是使用T.我可以强制转换为S使其编译,但这看起来也很难看……因为除了T之外的任何其他类型都会导致exception。
对于覆盖另一个方法的一种方法,它必须至少应用于重写方法的所有有效参数。 您的基本方法是通用public
。 因此它将接受任何扩展 List save(Iterable entities)T
类型S
但是,您的覆盖更具限制性,因为它只接受MyType
集合,因此它不是有效的覆盖。
如果您的基类使用T
定义,并且方法只接受T
,并且派生类将T
锁定为MyType
那么您应该没问题。
为了给出更好的答案,我们需要查看两个类的类声明。 我建议如下:
class MyClass{ public List save(Iterable entities); } class OtherClass extends MyClass{ public List save(Iterable entities); }
编辑:
如果您无法控制基类(您似乎没有),那么您将无法使用public
签名。 这是因为重写的方法是通用的,因此重写方法也必须如此 List save(Iterable structures)
取决于您如何定义,以下工作
public class TestGenerics2 { public List save(Iterable entities) { return new ArrayList(); } } public class TestGenerics3 extends TestGenerics2 { @Override public List save(Iterable entities) { return super.save(entities); } }
这是一个编译并显示如何使用它的示例:
abstract class A { abstract public List save(Iterable entities); } class B extends A> { @Override public > List save(Iterable entities) { return null; } } class C { public void useIt() { B b = new B(); Iterable> it = new ArrayList>(); b.save(it); } }
A类使用原始签名定义方法。 B
类实现它并为类型参数T
选择List
。 最后,类C
使用此方法, Iterable
whoregenerics类型是List
的子类。
以来
public List save(Iterable entities)
给出,你的覆盖必须是
public List save(Iterable structures)
并且您的实现必须尊重S可能是MyType的真实子类型。
你的方法
public List save(Iterable structures)
不是正确的覆盖:
- 因为Java> = 1.5允许协变返回类型而
List
是List
的子类型,这没关系,但是 - Java仅允许不变的参数类型,但
Iterable
是Iterable
的子Iterable
,因此您的编译器错误消息。
我的解决方案是不要覆盖这一点,只是创建一个服务类来完成所需的逻辑并保持存储库不变。