类型参数隐藏中的Java泛型
假设我有一个这样的接口类型参数隐藏中的Java泛型,java,generics,interface,wildcard,Java,Generics,Interface,Wildcard,假设我有一个这样的接口 public interface Foo<Ret, Arg> { public Ret doSomething(Arg arg); } 公共接口Foo{ 公共再剂量测定法(Arg-Arg); } 以及一个只具有包可见性的具体实现类 class FooImpl<Ret, Arg1, Arg2> implements Foo<Ret, Arg>, Bar<Ret, Arg1, Arg2> { // This
public interface Foo<Ret, Arg> {
public Ret doSomething(Arg arg);
}
公共接口Foo{
公共再剂量测定法(Arg-Arg);
}
以及一个只具有包可见性的具体实现类
class FooImpl<Ret, Arg1, Arg2> implements Foo<Ret, Arg>, Bar<Ret, Arg1, Arg2> {
// This class also implements something else making use of Arg2, so you cannot safely remove it
// But nothing relating to Arg2 is needed to create a FooImpl
}
类FooImpl实现Foo,Bar{
//此类还利用Arg2实现了其他功能,因此您无法安全地将其删除
//但是创建FooImpl不需要任何与Arg2相关的内容
}
(这可能发生的一个例子是在FooImpl
中实现Foo
和Bar
,将两个接口声明的方法转发给一个varargs方法)
现在,假设在同一个包中的某个地方有一个静态方法,它将FooImpl
作为Foo
返回。有人会认为您可以使用返回新的FooImpl(…)
,而实际上您不能(您必须使用一个具体的伪类型,如Arg2
,也就是说,..返回新的FooImpl(…)
)
你知道这是为什么吗,尤其是
Foo
接口和包可见性有效地隐藏了FooImpl
,不让任何使用静态方法的人看到吗?是不是因为人们仍然可以在某种程度上使用反射,以便到达FooImpl
的条
部分,其中需要具体的类型?我认为这与您的特定设计无关
您不能用通配符实例化类型
这也行不通:
return new ArrayList<?>();
返回新的ArrayList();
如果它真的这么做了,它还会做别的事情吗
return new ArrayList<Object>();
返回新的ArrayList();
您需要一个具体的类,但这并不意味着您需要在factory方法签名中显示它:
static <A,B> Foo<A,B> makeFoo(){
return new FooImpl<A,B, SomeTypeThatNoOneNeedsToSee>();
}
静态Foo makeFoo(){
返回新的FooImpl();
}
Java编译器努力做到不聪明。在许多情况下,它显然不需要一些信息来生成正确的代码,但它仍然会抱怨。当Java被发明的时候,全世界都看到了C以草率的态度试图编译所有东西,无论多么危险或愚蠢。javac
的目标是确保人们不能这样做
因此,它假设您提到Arg2
,这是有原因的——如果某件事情不需要它,您肯定不会将它放入代码中
解决方案:
Bar
时指定类型:class FooImpl实现Foo,Bar
BetterFooImpl扩展FooImpl
。这对API的使用者隐藏了第三个类型参数Bar的第三个参数
@SuppressWarning
注释的激增。当这种情况发生时,我会这样问,当我找不到我能理解的解决方案时,我会删除泛型。编写可维护代码比在泛型迷宫中找到聪明的方法更重要您收到的错误消息是什么?您是为构造函数获取的,还是在尝试为返回转换它时?静态方法的返回签名是什么?