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