方法签名中的Java泛型类型不匹配。

时间:2022-12-31 16:33:14

I have an Executor class that invokes instances of interface IService<T> with KeyList<T> argument.

我有一个Executor类,它调用接口IService 和KeyList 参数的实例。

   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.

但是您可能在运行时遇到其他问题。