11
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(QuerydslJpaRepositoryによって拡張される)のさまざまなsave()メソッドをオーバーライドしようとしています

クラスの定義:

public class MyTypeRepositoryImpl
    extends QueryDslJpaRepository<MyType, Long>
    implements MyTypeRepository

@NoRepositoryBean
public interface MyTypeRepository
    extends JpaRepository<MyType, Long>,
    QueryDslPredicateExecutor<MyType> 

そしてこれ(SpringDataから)

public class QueryDslJpaRepository<T, ID extends Serializable> 
extends SimpleJpaRepository<T, ID> 
implements QueryDslPredicateExecutor<T>

編集2:

このメソッドは各要素に対してsave(MyTypeエンティティ)を呼び出し、そのメソッドには次のロジックが含まれています。

  1. エンティティには一意のフィールドがあります
  2. そのフィールドの値を取得し、その値を持つエンティティがすでに存在するかどうかを確認します
  3. はいの場合、そのエンティティを使用します(entityManager.mergeを呼び出します)->機能しませんSではなくMyTypeを返します
  4. 新しいオブジェクトを作成しない場合->ここで新しいオブジェクトが作成されます。ジェネリック型では機能しません

4.の場合、id = nullを設定して、渡されたオブジェクトを使用できます。それは3では機能しません。

したがって、このメソッドにこのシグネチャがある理由には非常に戸惑います。それは私にとってそれを使用できなくし、TsDAOを使用してTのサブクラスを保存する理由がわかりません。が付いているのはsaveメソッドだけです。他のすべてはTを使用します。コンパイルするためにSにキャストすることもできますが、それも醜いようです...T以外のタイプは例外につながるためです。

4

5 に答える 5

12

あるメソッドが別のメソッドをオーバーライドするには、オーバーライドされたメソッドの少なくともすべての有効なパラメーターに適用する必要があります。基本メソッドは汎用public <S extends T> List<S> save(Iterable<S> entities)です。Sしたがって、を拡張するすべてのタイプを受け入れますT。ただし、オーバーライドはのコレクションのみを受け入れるため、より制限が厳しくなりMyTypeます。したがって、オーバーライドは有効ではありません。

基本クラスがで定義されていてT、メソッドがちょうどTで受け入れられ、派生クラスがロックダウンされTMyTypeいる場合は、問題ありません。

より良い答えを出すには、2つのクラスのクラス宣言を確認する必要があります。私は次のことを提案します:

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)署名が残っています。これは、オーバーライドされたメソッドが一般化されているため、オーバーライドされたメソッドも

于 2012-10-24T12:56:00.960 に答える
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);
    }
}
于 2012-10-24T13:05:23.150 に答える
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は、元のシグニチャを使用してメソッドを定義します。クラスBはそれを実装し、List<Integer>タイプパラメータを選択しますT。そして最後に、クラスCはこのメソッドをIterablewhoreジェネリック型がのサブクラスで使用しList<Integer>ます。

于 2012-10-24T13:03:25.763 に答える
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)

正しいオーバーライドではありません:

  • Java> = 1.5は共変の戻り型を許可List<MyType>し、のサブタイプであるList<S extends MyType>ため、これは問題ありませんが、
  • Javaは不変のパラメータタイプのみを許可しますIterable<MyType>が、のサブタイプでIterable<S extends MyType>あるため、コンパイラのエラーメッセージが表示されます。
于 2012-10-24T13:00:55.853 に答える
0

私の解決策は、これをまったくオーバーライドせずに、必要なロジックを実行するサービスクラスを作成し、リポジトリを変更しないことでした。

于 2012-12-10T09:28:43.063 に答える