You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

反射赋值ImmutableMap至Map字段报错,求解决方案

Bukkit插件修改PluginDescriptionFile的commands字段报错解决

问题场景

在Bukkit插件开发中,尝试通过反射修改PluginDescriptionFile里的commands字段(初始为ImmutableMap),添加自定义命令别名时抛出类型转换异常。

原代码

Field field = this.getDescription().getClass().getDeclaredField("commands");
Map<String, Map<String, Object>> commands = new HashMap<>();

this.getDescription().getCommands().forEach((c, v) -> commands.put(c, v));

for (String alias : this.aliasManager.getAllAliases()) {
    Map<String, Object> map = new HashMap<>();
    map.put("description", "An alias for " + aliasManager.getAlias(alias).getCommand());
    map.put("usage", "/<command>");
    map.put("name", alias);
    commands.put(alias, map);
}

Map<String, Map<String, Object>> immutableMap = ImmutableMap.copyOf(commands);

field.setAccessible(true);
field.set(this.getDescription().getCommands(), immutableMap);

报错信息

java.lang.IllegalArgumentException: Can not set java.util.Map field 
org.bukkit.plugin.PluginDescriptionFile.commands to com.google.common.collect.SingletonImmutableBiMap

字段声明

private Map<String, Map<String, Object>> commands = (Map<String, Map<String, Object>>)ImmutableMap.of();

解决方法

核心错误是反射设置字段时传入的目标对象错误:commands字段属于PluginDescriptionFile实例,而非getCommands()返回的Map对象。修正代码如下:

Field field = this.getDescription().getClass().getDeclaredField("commands");
Map<String, Map<String, Object>> commands = new HashMap<>();

// 复制原有命令到新Map
this.getDescription().getCommands().forEach(commands::put);

// 添加自定义别名命令
for (String alias : this.aliasManager.getAllAliases()) {
    Map<String, Object> map = new HashMap<>();
    map.put("description", "An alias for " + aliasManager.getAlias(alias).getCommand());
    map.put("usage", "/<command>");
    map.put("name", alias);
    commands.put(alias, map);
}

// 可选择转为ImmutableMap(保持原字段特性),或直接使用HashMap
Map<String, Map<String, Object>> targetMap = ImmutableMap.copyOf(commands);

field.setAccessible(true);
// 关键:传入PluginDescriptionFile实例作为字段所属对象
field.set(this.getDescription(), targetMap);

错误原因说明

原代码中field.set(this.getDescription().getCommands(), immutableMap)是错误的:

  1. field是PluginDescriptionFile类的成员字段,必须传入PluginDescriptionFile实例作为第一个参数,才能修改该实例的字段值。
  2. 之前传入的getCommands()返回的Map对象,并非字段所属的实例,JVM无法将ImmutableMap赋值给不属于它的字段,因此抛出类型不匹配异常。

另外,字段声明为Map接口,无论是ImmutableMap还是HashMap都符合类型要求,无需担心类型兼容问题,只要目标实例传对即可。

内容的提问来源于stack exchange,提问作者Gargant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 11:57:48