Java:如何覆盖这个通用方法? 公共列表保存(可编辑实体){ //... }

Java:如何覆盖这个通用方法? 公共列表保存(可编辑实体){ //... },java,generics,overriding,type-erasure,Java,Generics,Overriding,Type Erasure,如果我使用以下方法来重写 public <S extends T> List<S> save(Iterable<S> entities) { //... } @覆盖 公共列表保存(Iterable结构){ 列表结果=新建ArrayList(); //... 返回结果; } 我发现以下错误: @Override public List<MyType> save(Iterable<MyType> structures)

如果我使用以下方法来重写

public <S extends T> List<S> save(Iterable<S> entities) {
        //...
}
@覆盖
公共列表保存(Iterable结构){
列表结果=新建ArrayList();
//...
返回结果;
}
我发现以下错误:

@Override
public List<MyType> save(Iterable<MyType> structures) {
    List<MyType> result = new ArrayList<>();
    //...
    return result;
}
方法不重写或实现超类型中的方法
名称冲突:MyTypeRepositoryImpl中的save(Iterable)和SimpleParepository中的save(Iterable)具有相同的擦除,但两者都不重写另一个
其中S、T是类型变量:
S扩展在方法save(Iterable)中声明的T
T扩展类SimpleParepository中声明的对象
我怎样才能解决这个问题?我不需要这个方法是泛型的,事实上它不应该是泛型的。我的意思是

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
@覆盖
公共列表保存(Iterable结构){
列表结果=新建ArrayList();
//...
返回结果;
}
将不起作用,因为该方法可以创建与列表“不兼容”的MyType新对象

我怎样才能做到这一点

编辑:

请澄清。我正在尝试覆盖Spring数据SimpleParepository(由QuerydslJpaRepository扩展)的不同save()方法

类别定义:

@Override
public <S extends MyType> List<S> save(Iterable<S> structures) {
    List<S> result = new ArrayList<>();
    //...
    return result;
}
公共类MyTypeRepositoryImpl
扩展QueryDslJpaRepository
实现MyTypeRepository
@菜豆
公共接口MyTypeRepository
这是一个假设,
QueryDSL谓词执行器
这(来自Spring数据)

公共类QueryDslJpaRepository
扩展SimpleParepository
实现QueryDslPredicateExecutor
编辑2:

该方法为每个元素调用save(MyType实体),该方法包含以下逻辑:

  • 实体具有唯一的字段
  • 获取该字段值并检查具有该值的实体是否已存在
  • 如果是,则使用该实体(调用entityManager.merge)->不工作返回MyType not S
  • 如果没有创建新对象->此处创建新对象。不适用于泛型类型
  • 四个人。我可以设置id=null并使用传入的对象。这不适用于3人


    所以我很困惑为什么这个方法有这个签名。它使我无法使用,我不明白为什么我要使用Ts-DAO保存t的子类。save方法是唯一具有此功能的方法。其他所有方法都使用T。我可以将其强制转换为S以使其编译,但这看起来也很难看……因为T以外的任何其他类型都会导致异常。

    对于一个方法重写另一个方法,它必须至少应用于被重写方法的所有有效参数。基本方法是泛型
    公共列表保存(Iterable实体)
    。因此,它将接受扩展
    T
    的任何类型
    S
    。但是,您的覆盖更具限制性,因为它只接受
    MyType
    的集合,因此它不是有效的覆盖

    如果您使用
    T
    定义了基类,并且该方法只接受
    T
    ,并且派生类被锁定到
    T
    MyType
    ,那么您应该可以

    为了给出更好的答案,我们需要查看这两个类的类声明。我建议如下:

    public class QueryDslJpaRepository<T, ID extends Serializable> 
    extends SimpleJpaRepository<T, ID> 
    implements QueryDslPredicateExecutor<T>
    
    class-MyClass{
    公共列表保存(Iterable实体);
    }
    类OtherClass扩展了MyClass{
    公共列表保存(Iterable实体);
    }
    
    编辑:

    如果您不能控制基类(看起来好像没有),那么您就只能使用
    公共列表保存(Iterable structures)
    签名。这是因为重写方法是泛化的,因此重写方法也必须是

    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 T> List<S> save(Iterable<S> entities)
    
    公共列表保存(Iterable结构)
    
    您的实现必须考虑到S可能是MyType的真正子类型

    你的方法

    public <S extends MyType> List<S> save(Iterable<S> structures)
    
    公共列表保存(Iterable结构)
    
    不是正确的覆盖:

    • 因为Java>=1.5允许返回类型,并且
      List
      List
      的子类型,所以这是可以的,但是
    • Java只允许固定参数类型,但
      Iterable
      Iterable
      的子类型,因此编译器会显示错误消息

      • 下面是一个编译示例,展示了如何使用它:

        public List<MyType> save(Iterable<MyType> structures)
        
        抽象类A{
        抽象公共列表保存(Iterable实体);
        }
        B类扩展了A类{
        @凌驾
        公共列表保存(Iterable实体){
        返回null;
        }
        }
        C类{
        公共空间使用IT(){
        B=新的B();
        Iterable it=新的ArrayList();
        b、 保存(它);
        }
        }
        

        A
        定义具有原始签名的方法。类
        B
        实现它,并为类型参数
        T
        选择
        List
        。最后,class
        C
        将此方法用于
        Iterable
        whore泛型类型是
        列表的子类

        取决于您如何定义,以下工作

        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);
            }
        }
        
        公共类TestGenerics2{
        公共列表保存(Iterable实体){
        返回新的ArrayList();
        }
        }
        公共类TestGenerics3扩展了TestGenerics2{
        @凌驾
        公共列表保存(Iterable实体){
        返回super.save(实体);
        }
        }
        
        我的解决方案是根本不重写它,而是创建一个执行所需逻辑的服务类,并保持存储库不变。

        如何声明包含的类?列出“不兼容”是什么意思?从原始的
        参数来看,该类可以通过执行
        实现InterfaceName
        之类的操作来使用,而不必处理从注释到其他答案的子类以及您正在扩展一个您无法控制的类这一事实,我相信您是被迫使用
        公共列表保存(Iterable结构)
        。这是因为爱
        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);
            }
        }
        
        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);
            }
        }