使用反射设置非静态字段

时间:2012-07-23 02:56:22

标签: java minecraft

    public static void setMOTD(final String motd) throws Exception {
    final Field field = MinecraftServer.class.getDeclaredField("motd");
    final Field server = CraftServer.class.getDeclaredField("console");
    field.setAccessible(true);
    server.setAccessible(true);
    MinecraftServer instance = (MinecraftServer) server.get(CraftServer.class);
    field.set(instance, motd);
}

我的目标是在Minecraft服务器上更改当天的消息(运行craftbukkit)。为此,我需要更改非静态字段motd。我正在使用插件执行所有这些操作,因此我无法获取MinecraftServer的实例。最后一行是我尝试使用反射做到这一点,但失败了。我没有权限更改MinecraftServer类或CraftServer,因为它们位于外部库中。

motd和console都是非静态字段。

motd是一个带有修饰符public final的字符串。

console是MinecraftServer的一个实例,修饰符是最终保护的。

这是我得到的错误(在setMOTD的倒数第二行):

2012-07-22 22:16:31 [SEVERE] java.lang.IllegalArgumentException: Can not set final net.minecraft.server.MinecraftServer field org.bukkit.craftbukkit.CraftServer.console to java.lang.Class

3 个答案:

答案 0 :(得分:2)

重新阅读错误消息,似乎与您的代码不一致。错误消息似乎暗示您正在尝试将<{1}}成员变量设置为无效的对象类型。请确认您实际测试的代码。

答案 1 :(得分:2)

通过获取扩展CraftServer

的bukkit实例来解决
    public static void setServerMOTD(final String motd) throws Exception {
    final Field field = MinecraftServer.class.getDeclaredField("motd");
    final Field server = CraftServer.class.getDeclaredField("console");
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    field.setAccessible(true);
    server.setAccessible(true);
    modifiersField.setInt(server, server.getModifiers() & ~Modifier.FINAL);
    MinecraftServer instance = (MinecraftServer) server.get(Bukkit.getServer());
    field.set(instance, motd);
}

答案 2 :(得分:0)

根据错误消息,CraftServer类中的字段控制台看起来像'final'。

这意味着一旦设置,你将无法改变它,在镜像有机会修改它之前会发生这种情况。

如果CraftServer是库的一部分,您可能无法更改此行为