简体   繁体   English

使用反射在Java中获取静态私有哈希图

[英]Using reflection get a static private hashmap in java

I'm trying to find a way to extract a HashMap from a private static field within another class via Java. 我正在尝试找到一种通过Java从另一个类内的私有静态字段中提取HashMap的方法。

eg. 例如。

Inside FooClass there is a static field that looks like this: 在FooClass内部,有一个静态字段,如下所示:

private Map entityRenderMap;

Then in its construct it has: 然后在其构造中具有:

entityRenderMap = new HashMap();

How do you get the values within entityRenderMap via Reflection in Java? 您如何通过Java中的Reflection获取EntityRenderMap中的值? I've tried this but get errors: 我已经尝试过了,但是出现错误:

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

The error I get is: 我得到的错误是:

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

Are you certain it is a static field. 您确定这是一个静态字段吗? The javadoc of the get method clearly states: get方法的javadoc明确指出:

If the underlying field is a static field, the obj argument is ignored; 如果基础字段是静态字段,则obj参数将被忽略; it may be null. 它可以为空。

Otherwise, the underlying field is an instance field. 否则,基础字段是实例字段。 If the specified obj argument is null, the method throws a NullPointerException. 如果指定的obj参数为null,则该方法将引发NullPointerException。 If the specified object is not an instance of the class or interface declaring the underlying field, the method throws an IllegalArgumentException. 如果指定的对象不是声明基础字段的类或接口的实例,则该方法将引发IllegalArgumentException。

So with a static field you would not get the IllegalArgumentException since the parameter is ignored. 因此,对于静态字段,由于将忽略该参数,因此不会获得IllegalArgumentException Further, the code you posted shows it is not a static field but a regular field (since it lacks the word static , and its initialized in the constructor). 此外,您发布的代码显示它不是静态字段,而是常规字段(因为它缺少单词static ,并且在构造函数中对其进行了初始化)。

If you want to access the field of a certain instance A , you should pass that instance A to the Field#get method, and not the A.field as you are trying to do with your cl.get(this.entityRenderMap) call. 如果要访问某个实例A的字段,则应将该实例A传递给Field#get方法,而不是A.field给您的cl.get(this.entityRenderMap)调用。

You can take a look at this tutorial for some examples 您可以看一下本教程的一些示例

If the field is really static, you should pass null as an argument to cl.get() . 如果该字段确实是静态的,则应将null作为参数传递给cl.get()

If the field is not static, then you must pass the instance of FooClass which you want to get the field value from: 如果该字段不是静态的,那么必须传递FooClass实例,该实例要从以下位置获取字段值:

FooClass fc = new FooClass(); // or whatever, provided that fc is a FooClass instance
Object foo = cl.get(fc);

First, your code doesn't match your explanation. 首先,您的代码与您的解释不符。 Is it really a static field or is it not (your code says it's not)? 它是真的是静态字段还是不是(您的代码说不是)?

If it is static, you should pass null as argument to cl.get() (you don't need an instance to access static members). 如果它是静态的,则应将null作为参数传递给cl.get() (不需要实例来访问静态成员)。

However, I suspect that your field is actually not static, and your passing the wrong instance to cl.get() . 但是,我怀疑您的字段实际上不是静态的,并且您将错误的实例传递给cl.get() The JavaDocs to Field.get() state it would throw an IllegalArgumentException in this case. JavaDocs将Field.get()声明为在这种情况下将抛出IllegalArgumentException You need to pass a RenderManager instance to this method. 您需要将RenderManager实例传递给此方法。 Your code looks like your passing a Map (the entityRenderMap ). 您的代码看起来像是您传递了MapentityRenderMap )。

And last, is this code inside your RenderManager class? 最后,此代码是否在您的RenderManager类中? I suspect this, because your accessing a field with this with the same name as the field you want to set. 我对此表示怀疑,因为您使用与this名称相同的字段访问您要设置的字段。 In this case, don't use reflection at all! 在这种情况下,根本不要使用反射!

I'm assuming cl is a java.lang.reflect.Field . 我假设cljava.lang.reflect.Field The documentation states that Fields' get-method will throw: 文档指出,Fields的get方法将抛出:

IllegalArgumentException - if the specified object is not an instance of the class or interface declaring the underlying field (or a subclass or implementor thereof). IllegalArgumentException-如果指定的对象不是声明基础字段(或其子类或实现者)的类或接口的实例。

You should be passing the RenderManager -object to the get-method instead of the field (unless it's static, which it is not according to your example). 您应该将RenderManager -object传递给get方法而不是字段(除非它是静态的,根据您的示例,这不是静态的)。

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("");
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM