加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

Java泛型类的方法不适用于传递的参数

发布时间:2020-12-15 00:47:15 所属栏目:Java 来源:网络整理
导读:关于 Java泛型,我有一个“奇怪”的问题. 首先我列出我的代码: Service.class package jse.generics.service;public interface Service {} ServiceProvider.class package jse.generics.service;public interface ServiceProviderT extends Service { public
关于 Java泛型,我有一个“奇怪”的问题.

首先我列出我的代码:

Service.class

package jse.generics.service;

public interface Service {

}

ServiceProvider.class

package jse.generics.service;

public interface ServiceProvider<T extends Service> {

    public T getService();
}

ServiceProviderRegistry.class

package jse.generics.service;

import java.util.HashMap;
import java.util.Map;

public class ServiceProviderRegistry<T extends Service> {

     private Map<Class<T>,ServiceProvider<T>> map = new HashMap<Class<T>,ServiceProvider<T>>();

     public void register(Class<T> clazz,ServiceProvider<T> provider) {
          map.put(clazz,provider);
     }
}

FooService.class

package jse.generics.service;

public class FooService implements Service {

}

FooServiceProvider.class

package jse.generics.service;

public class FooServiceProvider implements ServiceProvider<FooService> {

     @Override
     public FooService getService() {
          return new FooService();
     }

}

ServiceTest.class

package jse.generics.service;

public class ServiceTest {

     /**
     * @param args
     */
     public static void main(String[] args) {
          ServiceProviderRegistry<? extends Service> registry = new ServiceProviderRegistry<Service>();
          registry.register(FooService.class,new FooServiceProvider());
     }

}

在ServiceTest类中,编译器抱怨registry.register方法不适用于传递给它的参数.我真的不知道为什么会发生这种情况.所以我很期待你的帮助来解决这个问题.

解决方法

在这种情况下,如果ServiceProviderRegistry不是参数化类,而是使寄存器方法(可能是相应的查找方法)通用,那么你会更好.在您当前的方法中,ServiceProviderRegistry< Service>只能注册Service.class,而不能注册Service的任何子类.

你真正关心的是传递给寄存器的类和提供者相互匹配,这是泛型方法的理想情况.

public class ServiceProviderRegistry {
  private Map<Class<?>,ServiceProvider<?>> registry = new HashMap<>();

  public <T extends Service> void register(Class<T> cls,ServiceProvider<T> provider) {
    registry.put(cls,provider);
  }

  @SuppressWarnings("unchecked")
  public <T extends Service> ServiceProvider<T> lookup(Class<T> cls) {
    return (ServiceProvider<T>)registry.get(cls);
  }
}

您将需要@SuppressWarnings注释 – 如果没有完全满足编译器的方式,则无法实现此模式,编译器只能访问编译时类型.在这种情况下,您知道强制转换在运行时始终是安全的,因为寄存器是唯一修改注册表映射的东西,因此@SuppressWarnings是合理的. Jon Skeet’s answer to this related question非常好地总结了它

Sometimes Java generics just doesn’t let you do what you want to,and you need to effectively tell the compiler that what you’re doing really will be legal at execution time.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读