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

使用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的实例对象。

解决方法

  1. 修正调用参数
    检查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);
      
  2. 增强代码健壮性(可选)

    • 在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 15:50:29