Используя отражение, получаем статический закрытый хэш-файл в Java - PullRequest
1 голос
/ 22 января 2012

Я пытаюсь найти способ извлечь HashMap из частного статического поля в другом классе через Java.

например.

Внутри FooClass есть статическое поле, которое выглядит следующим образом:

private Map entityRenderMap;

Тогда в своей конструкции он имеет:

entityRenderMap = new HashMap();

Как вы получаете значения в entityRenderMap через Reflection в Java? Я пробовал это, но получаю ошибки:

cl = RenderManager.class.getDeclaredField("entityRenderMap");
        cl.setAccessible(true);
        Object foo = cl.get(this.entityRenderMap);
        Mod.log(cl.getName());

Я получаю ошибку:

java.lang.IllegalArgumentException: Can not set java.util.Map field RenderManager.entityRenderMap to java.util.HashMap
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(Unknown Source)
at sun.reflect.UnsafeObjectFieldAccessorImpl.get(Unknown Source

Ответы [ 5 ]

2 голосов
/ 22 января 2012

Если поле действительно статическое, вы должны передать null в качестве аргумента cl.get().

Если поле не является статическим, вы должны передать экземпляр FooClass, который вы хотитеполучить значение поля из:

FooClass fc = new FooClass(); // or whatever, provided that fc is a FooClass instance
Object foo = cl.get(fc);
2 голосов
/ 22 января 2012

Во-первых, ваш код не соответствует вашему объяснению. Это действительно статическое поле или нет (ваш код говорит, что это не так)?

Если он статический, вы должны передать null в качестве аргумента cl.get() (вам не нужен экземпляр для доступа к статическим членам).

Однако я подозреваю, что ваше поле на самом деле не статично, и вы передали неправильный экземпляр в cl.get(). JavaDocs для Field.get() заявляет, что в этом случае будет выброшено IllegalArgumentException. Вам нужно передать экземпляр RenderManager этому методу. Ваш код выглядит как ваша передача Map (entityRenderMap).

И, наконец, этот код в вашем RenderManager классе? Я подозреваю это, потому что вы обращаетесь к полю с this с тем же именем, что и поле, которое вы хотите установить. В этом случае вообще не используйте отражение!

2 голосов
/ 22 января 2012

Вы уверены, что это статическое поле?В javadoc метода get четко указано:

Если базовое поле является статическим полем, аргумент obj игнорируется;оно может быть нулевым.

В противном случае базовое поле является полем экземпляра.Если указанный аргумент obj имеет значение null, метод генерирует исключение NullPointerException.Если указанный объект не является экземпляром класса или интерфейса, объявляющего базовое поле, метод генерирует исключение IllegalArgumentException.

Таким образом, со статическим полем вы не получите IllegalArgumentException, поскольку параметригнорируются.Кроме того, код, который вы опубликовали, показывает, что это не статическое поле, а обычное поле (так как в нем отсутствует слово static, и оно инициализируется в конструкторе).

Если вы хотите получить доступ к полю поляопределенный экземпляр A, вы должны передать этот экземпляр A методу Field#get, а не A.field, как вы пытаетесь сделать с помощью вызова cl.get(this.entityRenderMap).

Вы можете взятьпосмотрите на этот урок для некоторых примеров

1 голос
/ 22 января 2012

Я предполагаю, что cl - это java.lang.reflect.Field . В документации говорится, что get-метод Fields будет выдавать:

IllegalArgumentException - если указанный объект не является экземпляром класса или интерфейса, объявляющего основное поле (или подкласс или его реализатор).

Вы должны передавать RenderManager -объект в метод get вместо поля (если оно не статическое, что не соответствует вашему примеру).

0 голосов
/ 22 января 2012
vim Test.java
    import java.util.*;
    import com.dp4j.*;

class FooClass{

private static Map entityRenderMap;

FooClass(){
entityRenderMap = new HashMap();
}

}

public class Test{
@Reflect
public static void main(String... args){

Map reflectEntityMap = FooClass.entityRenderMap;
}
}


javac -cp ~/ws/dp4j/dp4j.jar -Averbose=true Test.java
Test.java:16: Note: 
import java.util.*;
import com.dp4j.*;

class FooClass {
    private static Map entityRenderMap;

    FooClass() {
        entityRenderMap = new HashMap();
    }
}
public class Test {

    public Test() {
        super();
    }

    @Reflect()
    public static void main(String... args) throws java.lang.ClassNotFoundException, java.lang.NoSuchFieldException, java.lang.IllegalArgumentException, java.lang.IllegalAccessException {
        java.lang.reflect.Field entityRenderMapField = null;
        entityRenderMapField = Class.forName("FooClass").getDeclaredField("entityRenderMap");
        entityRenderMapField.setAccessible(true);
        Map reflectEntityMap;
        reflectEntityMap = (.java.util.Map)entityRenderMapField.get("");
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...