I have an Executor
class that invokes instances of interface IService<T>
with KeyList<T>
argument.
我有一个Executor类,它调用接口IService
class Executor{
KeyList<?> _keys;
IService<?> _service;
public Executor(IService<?> service, KeyList<?> keys){
_service = service;
_keys = keys;
}
public void execute(){
_service.invoke(_keys);
}
}
interface IService<T>{
public void invoke( KeyList<T> keys);
}
class KeyList<T> {
List<T> _list;
}
I used <?>
for the Executor's members since it does not care how IService and KeyList are parameterized, but the following raises a compilation error saying the arguments are not applicable:
我使用< ?对于Executor的成员来说>,因为它不关心IService和KeyList是如何参数化的,但是下面提出了一个编译错误,表示这些参数不适用:
public void execute(){
_service.invoke(_keys); //error on invoke
}
I'm guessing it's complaining becuase KeyList<?>
is not equal to KeyList<T>
, but <?>
is the same as <? extends Object>
, so I'm a bit confused. Is there a better alternative?
我猜它是在抱怨,因为KeyList
不等于KeyList
2 个解决方案
#1
3
A wildcard (?
) represents some specific unknown type. But you're dealing with two separate wildcards here - they may not be the same. Use the following instead:
通配符(?)表示某种特定的未知类型。但你要处理的是两个单独的通配符,它们可能不一样。使用以下:
class Executor<T> {
KeyList<T> _keys;
IService<T> _service;
public Executor(IService<T> service, KeyList<T> keys){
_service = service;
_keys = keys;
}
public void execute(){
_service.invoke(_keys);
}
}
This declares a type parameter T
for the class Executor
, and then uses it as a type argument for _keys
and _service
, ensuring they're compatible.
这为类执行器声明了一个类型参数T,然后将其用作_keys和_service的类型参数,以确保它们是兼容的。
If you can't parameterize Executor
, try using a parameterized helper class:
如果不能参数化Executor,可以尝试使用参数化助手类:
class Executor {
private static final class ServiceAndKeys<T> {
private final KeyList<T> keys;
private final IService<T> service;
ServiceAndKeys(IService<T> service, KeyList<T> keys) {
this.service = service;
this.keys = keys;
}
void execute() {
service.invoke(keys);
}
}
private final ServiceAndKeys<?> serviceAndKeys;
public <T> Executor(IService<T> service, KeyList<T> keys){
serviceAndKeys = new ServiceAndKeys<T>(service, keys);
}
public void execute() {
serviceAndKeys.execute();
}
}
#2
2
When you eventually assign
当你最终分配
IService<?> _service;
it will have some type. Consider this a type-1
.
它会有某种类型。考虑一个1型。
When you eventually assign
当你最终分配
KeyList<?> _keys;
it will have some type. Consider this a type-2
.
它会有某种类型。考虑这2型。
Nothing says that these types are compatible and therefore the compiler doesn't allow it. This has to do with Capture Conversion.
没有说这些类型是兼容的,因此编译器不允许它。这与捕获转换有关。
If Ti is a wildcard type argument (§4.5.1) of the form ?, then Si is a fresh type variable whose upper bound is Ui[A1:=S1,...,An:=Sn] and whose lower bound is the null type (§4.1).
如果Ti是表单的通配符类型参数(4.5.1),那么Si是一个新的类型变量,其上界是Ui[A1:=S1,…一:= Sn)和零下界的类型(§4.1)。
Therefore each <?>
is a different type variable.
因此每个< ?>是一个不同的类型变量。
An ugly solution is to simply remove the wildcard type declaration altogether
一个丑陋的解决方案是完全删除通配符类型声明。
KeyList _keys;
IService _service;
but you may run into other troubles at runtime.
但是您可能在运行时遇到其他问题。
#1
3
A wildcard (?
) represents some specific unknown type. But you're dealing with two separate wildcards here - they may not be the same. Use the following instead:
通配符(?)表示某种特定的未知类型。但你要处理的是两个单独的通配符,它们可能不一样。使用以下:
class Executor<T> {
KeyList<T> _keys;
IService<T> _service;
public Executor(IService<T> service, KeyList<T> keys){
_service = service;
_keys = keys;
}
public void execute(){
_service.invoke(_keys);
}
}
This declares a type parameter T
for the class Executor
, and then uses it as a type argument for _keys
and _service
, ensuring they're compatible.
这为类执行器声明了一个类型参数T,然后将其用作_keys和_service的类型参数,以确保它们是兼容的。
If you can't parameterize Executor
, try using a parameterized helper class:
如果不能参数化Executor,可以尝试使用参数化助手类:
class Executor {
private static final class ServiceAndKeys<T> {
private final KeyList<T> keys;
private final IService<T> service;
ServiceAndKeys(IService<T> service, KeyList<T> keys) {
this.service = service;
this.keys = keys;
}
void execute() {
service.invoke(keys);
}
}
private final ServiceAndKeys<?> serviceAndKeys;
public <T> Executor(IService<T> service, KeyList<T> keys){
serviceAndKeys = new ServiceAndKeys<T>(service, keys);
}
public void execute() {
serviceAndKeys.execute();
}
}
#2
2
When you eventually assign
当你最终分配
IService<?> _service;
it will have some type. Consider this a type-1
.
它会有某种类型。考虑一个1型。
When you eventually assign
当你最终分配
KeyList<?> _keys;
it will have some type. Consider this a type-2
.
它会有某种类型。考虑这2型。
Nothing says that these types are compatible and therefore the compiler doesn't allow it. This has to do with Capture Conversion.
没有说这些类型是兼容的,因此编译器不允许它。这与捕获转换有关。
If Ti is a wildcard type argument (§4.5.1) of the form ?, then Si is a fresh type variable whose upper bound is Ui[A1:=S1,...,An:=Sn] and whose lower bound is the null type (§4.1).
如果Ti是表单的通配符类型参数(4.5.1),那么Si是一个新的类型变量,其上界是Ui[A1:=S1,…一:= Sn)和零下界的类型(§4.1)。
Therefore each <?>
is a different type variable.
因此每个< ?>是一个不同的类型变量。
An ugly solution is to simply remove the wildcard type declaration altogether
一个丑陋的解决方案是完全删除通配符类型声明。
KeyList _keys;
IService _service;
but you may run into other troubles at runtime.
但是您可能在运行时遇到其他问题。