Java 仿制药警告需要上师冥想

Java generics warning requiring guru meditation

我有一些 Java 代码,如以下代码片段(示例是从原始代码简化而来)。出现黄色波浪线和警告消息,如下面的代码注释所示。消息是:"This method invocation is unsafe since the passed arguments may be of a wrong type."

abstract class Seek<T> {
    abstract <S> Seek<S> seek(S... o);
    abstract <T2> void map(Func<T,T2> call);
    interface Func<I,O> {
        public O call(I x);
    }
    public <X2> void go(Func<T,X2> c, T some) {
        seek(some).map(c); // <- yellow squiggle here on 'c'
    }
}

为什么会出现警告?解决此问题的最佳方法是什么?

注意: 我正在为 Android.

使用 AIDE 开发环境

编辑:我在阅读@tsolakp 和@LouisWasserman 的回答后修复了代码中的一个错误。

map 应该只有 T2 作为类型参数,而不是 T。现在 TSeek<T> class 中隐藏了 T,也就是说,您有两个名为 T 的类型变量,它们实际上是不同的,您不希望这样.

我在编译您的代码时收到的警告与从 seek(S...) 方法创建通用数组有关。

如果可以将其更改为 List<S>,则可以使用 Arrays.asList():

调用它
abstract class Seek<T> {
    abstract <S> Seek<S> seek(List<S> o);

    // ...

    public <X1,X2> void go(Func<X1,X2> c, X1 some) {
        seek(Arrays.asList(some)).map(c);
    }
}

map方法中将T改为T1。 您还将收到通用数组警告。这是没有警告的修改版本:

abstract static class Seek<T> {

    abstract <S> Seek<S> seek(List<S> s);

    abstract <T1,T2> void map(Func<T1, T2> call);

    interface Func<I,O> {
        public O call(I x);
    }

    public <X1,X2> void go(Func<X1,X2> c, X1 some) {
        seek( Arrays.asList(some) ).map(c); 
    }
}

经过一些评论,OP 可能打算使 map 方法与 Seek class 泛型绑定。如果是这样的话,我们可以使用这个解决方案,正如@Louis Wasserman 和@Andy Turner 所建议的那样:

abstract static class Seek<T> {

    abstract <S> Seek<S> seek(List<S> s);

    abstract <T2> void map(Func<T, T2> call);

    interface Func<I,O> {
        public O call(I x);
    }

    public <X1,X2> void go(Func<X1,X2> c, X1 some) {
        seek( Arrays.asList(some) ).map(c); 
    }
}

实际上该代码中有三个警告:

  1. Type safety: Potential heap pollution via varargs parameter o at abstract <S> Seek<S> seek(S... o);

  2. The type parameter T is hiding the type T at abstract <T,T2> void map(Func<T,T2> call);

  3. Type safety: A generic array of X1 is created for a varargs parameter at seek(some).map(c);

可以清除警告 A. 从​​泛型中取出 varargs 参数,如:

abstract class Seek<T> {
   abstract <S> Seek<S> seek(S o); // <- no more yellow squiggle
   abstract <T1,T2> void map(Func<T1,T2> call); // <- no more yellow squiggle
   interface Func<I,O> {
      public O call(I x);
   }
   public <X1,X2> void go(Func<X1,X2> c, X1 some) {
      seek(some).map(c); // <- no more yellow squiggle here on 'c'
   }
 }

乙。明确定义数组,如:

  abstract class Seek<T> {
  abstract <S> Seek<S> seek(S[] o);        // <- no more yellow squiggle
  abstract <T2> void map(Func<T,T2> call); // <- no more yellow squiggle
  interface Func<I,O> {
    public O call(I x);
  }
  public <X1,X2> void go(Func<X1,X2> c, X1[] some) {
    seek(some).map(c); // <- no more yellow squiggle
  }
}

但是,S[] oS... o完全不同。它只能明确地接受数组。也许您需要重新考虑您的设计?

恕我直言:我真的不明白在 class 和方法级别上需要同时拥有那么多泛型类型参数...