samedi 30 décembre 2017

Reflection - Set Interface Type Field

I am using reflection to edit a private (final) Map, then save it back to its original field (since its object class has no public methods for editing the map):

    Field field = null, field2 = null, modifiersField = null;
    // Get map field
    field = SimpleReloadableResourceManager.class.getDeclaredField("domainResourceManagers");
    // Make accessible
    field.setAccessible(true);

    // Get instance
    @SuppressWarnings("unchecked")
    Map<String, FallbackResourceManager> domainResourceManagers = (Map<String, FallbackResourceManager>) field.get(Minecraft.getMinecraft().getResourceManager());
    if (domainResourceManagers.get(FinalStrings.ID + "tmp") == null || !(domainResourceManagers.get(FinalStrings.ID + "tmp") instanceof ImportResourceManager)) {

        // Access other private resource
        field2 = Minecraft.class.getDeclaredField("metadataSerializer_");
        // Make accessible
        field2.setAccessible(true);
        MetadataSerializer ser = (MetadataSerializer) field2.get(Minecraft.getMinecraft());

        // Edit map instance
        domainResourceManagers.put(FinalStrings.ID + "tmp", new ImportResourceManager(ser));

        // Remove final modifier
        modifiersField = Field.class.getDeclaredField("modifiers");
        modifiersField.setAccessible(true);
        modifiersField.set(field, field.getModifiers() & ~Modifier.FINAL);
        // Set map field (throws exception)
        field.set(domainResourceManagers, Minecraft.getMinecraft().getRenderManager());
    } else {
        field.setAccessible(false);
        return;
    }

This is throwing an exception saying that a Map cannot be set to a HashMap:

 java.lang.IllegalArgumentException: Can not set final java.util.Map field net.minecraft.client.resources.SimpleReloadableResourceManager.domainResourceManagers to java.util.HashMap

But java.util.Map is an interface, so I cannot set this field without constructing a new interface object in the middle of my code.

How should I go about using reflection to set an interface type field?





Aucun commentaire:

Enregistrer un commentaire