[英]Java:How to override this generic method?
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 entity) ,該方法包含以下邏輯:
對於 4. 我可以設置 id = null 並使用傳入的對象。 這對 3 不起作用。
所以我很疑惑為什么這個方法有這個簽名。 它使我無法使用它,我不明白為什么要使用 Ts DAO 保存 T 的子類。 save 方法是唯一帶有 . 所有其他人都只使用 T。我可以將其強制轉換為 S 以使其編譯,但這看起來也很丑陋……因為除 T 之外的任何其他類型都會導致異常。
一個方法要覆蓋另一個方法,它必須至少應用於被覆蓋方法的所有有效參數。 您的基本方法是通用public <S extends T> List<S> save(Iterable<S> entities)
。 所以它將接受任何擴展T
類型S
。 但是,您的覆蓋更具限制性,因為它只接受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);
}
編輯:
如果您無法控制基類(似乎您沒有),那么您將被public <S extends MyType> List<S> save(Iterable<S> structures)
簽名卡住。 這是因為覆蓋的方法是泛化的,因此覆蓋的方法也必須是
取決於您如何定義,以下工作
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);
}
}
這是一個編譯示例並展示了如何使用它:
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
定義與原始簽名的方法。 B
類實現它並為類型參數T
選擇List<Integer>
。 最后,類C
將此方法與Iterable
whore 泛型類型一起使用,它是List<Integer>
的子類。
自從
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>
的子Iterable<S extends MyType>
,因此您的編譯器錯誤消息。我的解決方案是根本不覆蓋它,而是創建一個執行所需邏輯並保持存儲庫不變的服務類。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.