使用Java反射向其他类的protected ArrayList添加元素报错求助
解决Minecraft模组反射修改生物群系怪物列表的类型错误
问题背景
开发Minecraft模组时,尝试通过Java反射访问BiomeGenBase类中的protected实例字段spawnableMonsterList并添加怪物,但调用addMonster方法时触发类型错误,报错提示无法将List字段设置为Class类型。
原代码
LivingEntityHelper类
public class LivingEntityHelper { static Field monsterList; static { try{ Field[] feilds = BiomeGenBase.class.getDeclaredFields(); for(Field feild : feilds) { if(feild.getName().equals("spawnableMonsterList")) { monsterList = feild; } } if(monsterList == null) throw new RuntimeException("Could not find spawnableMonsterList feild!"); monsterList.setAccessible(true); }catch (Exception e) { throw new RuntimeException(e); } } @SuppressWarnings("unchecked") public static void addMonster(SpawnListEntry monster, Object biome){ try { ((List<SpawnListEntry>) monsterList.get(biome)).add(monster); }catch (Exception e) { throw new RuntimeException(e); } } }
BiomeGenBase类相关定义
protected List<SpawnListEntry> spawnableMonsterList; // 构造器中初始化: this.spawnableMonsterList = new ArrayList();
报错信息
[18:57:32] [Minecraft main thread] java.lang.RuntimeException: java.lang.IllegalArgumentException: Can not set java.util.List field net.minecraft.src.BiomeGenBase.spawnableMonsterList to java.lang.Class [18:57:32] [Minecraft main thread] at com.example.examplemod.util.LivingEntityHelper.addMonster(LivingEntityHelper.java:35) [18:57:32] [Minecraft main thread] at com.example.examplemod.ExampleMod.init(ExampleMod.java:15) [18:57:32] [Minecraft main thread] at bta.ModLoader.loadMod(ModLoader.java:120) [18:57:32] [Minecraft main thread] at bta.ModLoader.init(ModLoader.java:76) [18:57:32] [Minecraft main thread] at net.minecraft.client.Minecraft.startGame(Minecraft.java:309) [18:57:32] [Minecraft main thread] at net.minecraft.client.Minecraft.run(Minecraft.java:566) [18:57:32] [Minecraft main thread] at java.base/java.lang.Thread.run(Thread.java:833) [18:57:32] [Minecraft main thread] Caused by: java.lang.IllegalArgumentException: Can not set java.util.List field net.minecraft.src.BiomeGenBase.spawnableMonsterList to java.lang.Class [18:57:32] [Minecraft main thread] at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167) [18:57:32] [Minecraft main thread] at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171) [18:57:32] [Minecraft main thread] at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58) [18:57:32] [Minecraft main thread] at java.base/jdk.internal.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:36) [18:57:32] [Minecraft main thread] at java.base/java.lang.reflect.Field.get(Field.java:425) [18:57:32] [Minecraft main thread] at com.example.examplemod.util.LivingEntityHelper.addMonster(LivingEntityHelper.java:33) [18:57:32] [Minecraft main thread] ... 6 more
问题原因
spawnableMonsterList是实例字段(非static),必须传入BiomeGenBase的具体实例才能通过Field.get()获取对应实例的列表。报错的核心是调用addMonster时传入的biome参数是Class对象(比如BiomeGenBase.class),而非BiomeGenBase的实例对象。
解决方法
修正调用参数
检查ExampleMod.init中调用addMonster的代码,确保传入的是BiomeGenBase的实例(比如游戏内置的生物群系实例,如BiomeGenBase.forest、BiomeGenBase.desert等,不同版本的MC可能实例命名不同)。- 错误调用示例:
LivingEntityHelper.addMonster(new SpawnListEntry(MyMonster.class, 10, 4, 4), BiomeGenBase.class); - 正确调用示例:
LivingEntityHelper.addMonster(new SpawnListEntry(MyMonster.class, 10, 4, 4), BiomeGenBase.forest);
- 错误调用示例:
增强代码健壮性(可选)
- 在
addMonster方法中添加参数类型校验,提前拦截错误输入:@SuppressWarnings("unchecked") public static void addMonster(SpawnListEntry monster, Object biome){ if (!(biome instanceof BiomeGenBase)) { throw new IllegalArgumentException("biome参数必须是BiomeGenBase的实例,不能传入Class对象"); } try { ((List<SpawnListEntry>) monsterList.get(biome)).add(monster); }catch (Exception e) { throw new RuntimeException(e); } } - 优化字段查找逻辑,直接使用
getDeclaredField替代遍历,提升效率:static { try{ monsterList = BiomeGenBase.class.getDeclaredField("spawnableMonsterList"); monsterList.setAccessible(true); }catch (NoSuchFieldException e) { throw new RuntimeException("Could not find spawnableMonsterList field!", e); }catch (Exception e) { throw new RuntimeException(e); } }
- 在
内容的提问来源于stack exchange,提问作者Dilosir 22
相关产品推荐
相关产品推荐

