首页 > 解决方案 > 使用反射更改最终变量,或在代码中设置它之前更改它调用的内容

问题描述

所以基本上,我正在尝试获取一个 Minecraft 变量(不受支持的版本,而且没人知道它是什么时候发生的),我需要将变量所具有的块更改为一个新块。我检查了这个问题,结果发现尝试设置最终变量不起作用,因为使用它的代码仍然返回旧值,而使用反射变量的代码返回新值。有人让它在 1.7.2 上工作,但我使用的是 1.7.10 并且代码不再适用于该版本,我前一段时间对其进行了测试。不幸的是,我找不到此代码的来源线程,并且我不再拥有它。

我希望在这一行中将“new BlockFence(“planks_oak”,Material.wood)”更改为“new BlockNewFence(“planks_oak”,Material.wood)”,但我对反射很陌生,不知道如何. 这是行:

blockRegistry.addObject(85, "fence", (new BlockFence("planks_oak", Material.wood)).setHardness(2.0F).setResistance(5.0F).setStepSound(soundTypeWood).setBlockName("fence"));

感谢阅读,如果有的话。我自己尝试过,但老实说一无所获,因为我真的不确定该怎么做才能实现这一点,我真的只知道如何获取和设置一个私有/受保护的字段,但正如我之前发现的那样,最终字段并没有真正起作用一样的方法。如果我需要提供更多信息,请告诉我。我之前提到 final 字段和东西的原因是因为 blockRegistry 和使用这个注册表项的变量都是 final 的。

标签: javareflectionminecraft

解决方案


很简单,你可以试试。但请注意,这不是一个好方法。您可能会遭受无法预料的行为。

static class Value {
    public static final Integer VALUE = 10;
}

static void setFinalField(Field field, Object newValue) throws Exception {
    field.setAccessible(true);
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
    field.set(null, newValue);
}
public static void main(String args[]) throws Exception {
    setFinalField(Value.class.getField("VALUE"), 200);
    System.out.println(Value.VALUE); //200 here
}

推荐阅读