Java 8调用RuntimeTypeAdapterFactory.of报标签不唯一错误如何解决
问题根因
你遇到的java.lang.IllegalArgumentException: types and labels must be unique报错和Java 8不支持List.of无关,该报错是RuntimeTypeAdapterFactory的内置校验逻辑触发:要求注册的所有子类型Class、对应的type字段标签值必须全局唯一,不可重复。
你感知到报错出现在RuntimeTypeAdapterFactory.of行属于行号对齐偏差,实际报错触发点是后续循环调用factory.registerSubtype的步骤,堆栈日志也明确指向registerSubtype方法。
常见触发场景:
Stix2Type.TYPES枚举中存在重复的implementation类,或者重复的toJsonString()返回值- 你多次调用了
commonGsonBuilder方法,由于Stix2Type是枚举单例,首次调用时已经通过setImplementation设置过实现类、注册过子类型,第二次调用时重复注册触发校验
解决方案
方案1:添加重复校验+单次初始化逻辑
调整代码避免重复注册,同时提前做去重处理:
// 增加全局标记,避免重复初始化枚举实现类 private static volatile boolean stixTypeInitialized = false; public static GsonBuilder commonGsonBuilder(Map<Stix2Type, Class<? extends TypedStixObject>> customImplementations) { RuntimeTypeAdapterFactory<TypedStixObject> factory = RuntimeTypeAdapterFactory.of(TypedStixObject.class, "type", true); // 只在首次调用时设置枚举实现类,避免重复修改 if (!stixTypeInitialized) { synchronized (Stix2Gson.class) { if (!stixTypeInitialized) { for (Stix2Type stix2Type : customImplementations.keySet()) { stix2Type.setImplementation(customImplementations.get(stix2Type)); } stixTypeInitialized = true; } } } // 注册前先去重,避免重复的类或者标签 Map<Class<?>, String> classToLabel = new HashMap<>(); Map<String, Class<?>> labelToClass = new HashMap<>(); for (Stix2Type value : Stix2Type.TYPES) { Class<?> implClazz = value.getImplementation(); String label = value.toJsonString(); // 跳过重复的注册项 if (classToLabel.containsKey(implClazz) || labelToClass.containsKey(label)) { continue; } classToLabel.put(implClazz, label); labelToClass.put(label, implClazz); factory.registerSubtype(implClazz, label); } return new GsonBuilder() .disableHtmlEscaping() .registerTypeHierarchyAdapter(Collection.class, new EmptyCollectionNonSerializer()) .registerTypeHierarchyAdapter(Stix2Type.class, new Stix2TypeSerializer()) .registerTypeHierarchyAdapter(Stix2Type.class, new Stix2TypeDeserializer()) .registerTypeAdapterFactory(factory); }
方案2:兼容Java 8的RuntimeTypeAdapterFactory替换
如果你使用的eu.csaware.stix2.common.RuntimeTypeAdapterFactory内部实现用到了Java 9+的List.of语法,可以直接替换为Gson官方兼容Java 8的RuntimeTypeAdapterFactory实现,将官方开源的对应类代码复制到你的项目同路径下覆盖原有类即可,官方实现没有使用高版本Java语法。
内容的提问来源于stack exchange,提问作者AnaGutiFontan
相关产品推荐
相关产品推荐

