Java泛型HttpClient工厂类调用put方法类型不匹配编译报错问题
问题原因
你遇到的编译错误是Java泛型上界通配符的固有使用限制:
- 你工厂返回的类型是
PreferencesHTTPClient<? extends ISystemPreferences>,其中通配符?代表某个未知的、实现了ISystemPreferences的类,编译器无法确认这个未知类型和你传入的DutPreferencesDTO是匹配的,所以会禁止调用参数类型包含通配符的put方法(上界通配符仅允许读取返回值符合上界的方法,不允许传入参数的写入操作,避免类型安全问题)。
另外你的代码还有两个隐藏问题:
- 单例实现没有做线程安全控制,多线程并发调用时可能会生成多个工厂实例
PreferencesHTTPClient中的route被声明为静态变量,会导致所有客户端实例的路由地址被最后创建的实例覆盖
修复方案
1. 改造工厂类
增加泛型方法做类型转换,同时修复单例线程安全问题:
public class SystemPreferencesFactory { // 增加volatile修饰禁止指令重排 private static volatile SystemPreferencesFactory factory = null; private Map<String, PreferencesHTTPClient<? extends ISystemPreferences>> preferencesMap; private SystemPreferencesFactory(){ this.preferencesMap = Map.of( PreferencesHTTPType.DUT_PREFERENCES.getName(), new PreferencesHTTPClient<DutPreferencesDTO>(PreferencesHTTPType.DUT_PREFERENCES.getUrl()), PreferencesHTTPType.MACHINE_PROPERTIES.getName(), new PreferencesHTTPClient<MachineProperties>(PreferencesHTTPType.MACHINE_PROPERTIES.getUrl()) ); } // 泛型方法自动适配调用方需要的类型 @SuppressWarnings("unchecked") public static <T extends ISystemPreferences> PreferencesHTTPClient<T> getPreferencesHTTPClient(String type) { if (factory == null) { synchronized (SystemPreferencesFactory.class) { if (factory == null) { factory = new SystemPreferencesFactory(); } } } return (PreferencesHTTPClient<T>) factory.preferencesMap.get(type); } }
2. 修正PreferencesHTTPClient的静态变量问题
去掉route的static修饰符:
public class PreferencesHTTPClient<T> extends HTTPClient { private static final Logger logger = LoggerManager.getLogger(); // 去掉static修饰,改为实例变量 private String route = ""; // 其余代码保持不变 }
3. 调用代码调整
编译器会自动推断泛型类型,你也可以显式指定泛型提高可读性:
// 自动推断写法 SystemPreferencesFactory.getPreferencesHTTPClient(PreferencesHTTPType.DUT_PREFERENCES.getName()) .put(converterUtil.DutFromEntityToDTO(dp)); // 显式指定泛型写法 SystemPreferencesFactory.<DutPreferencesDTO>getPreferencesHTTPClient(PreferencesHTTPType.DUT_PREFERENCES.getName()) .put(converterUtil.DutFromEntityToDTO(dp));
内容的提问来源于stack exchange,提问作者Gilad Dahan
相关产品推荐
相关产品推荐

