我有一些Java代码,如下面的代码片段(该示例是从原始代码简化而来的(。将显示黄色波浪线和警告消息,如下面的代码注释所示。消息是:"此方法调用不安全,因为传递的参数可能属于错误的类型。
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的答案后修复了代码中的错误。
实际上,该代码中有三个警告:
-
类型安全:通过变量参数o进行潜在的堆污染 在
abstract <S> Seek<S> seek(S... o);
-
类型参数 T 在
abstract <T,T2> void map(Func<T,T2> call);
处隐藏类型 T -
类型安全:在
seek(some).map(c);
处为 varargs 参数创建 X1 的泛型数组
它可以清除警告 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'
}
}
B. 显式定义数组,如下所示:
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[] o
与S... o
完全不同. 它只能显式地采用数组。也许您需要重新考虑您的设计?
恕我直言:我真的不明白需要在类和方法级别同时拥有那么多泛型类型参数......
map
应该只将T2
作为类型参数,而不是T
。 现在,T
从Seek<T>
类中遮蔽了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
。如果是这种情况,我们可以按照@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);
}
}