java NoSuchFieldException 使用 getDeclaredField() 并且字段存在时

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28517424/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 13:44:15  来源:igfitidea点击:

NoSuchFieldException when using getDeclaredField() and field exists

javareflection

提问by Fullstack

java.lang.NoSuchFieldException: c
at java.lang.Class.getDeclaredField(Unknown Source)
at ru.onlymc.OnlyMZ.CustomEntityType.getPrivateStatic(CustomEntityType.java:177)

java.lang.NoSuchFieldException: c
at java.lang.Class.getDeclaredField(Unknown Source)
at ru.onlymc.OnlyMZ.CustomEntityType.getPrivateStatic(CustomEntityType.java:177)

Method:

方法:

private static Object getPrivateStatic(Class clazz, String f) throws Exception {
    Field field = clazz.getDeclaredField(f);
    field.setAccessible(true);
    return field.get(null);
}

Calling:

调用:

private static void a(Class paramClass, String paramString, int paramInt) {
    try {
        ((Map) getPrivateStatic(sg.class, "c")).put(paramString, paramClass);
        //...
    } catch (Exception exc) {
        exc.printStackTrace();
    }
}

sg.class(from decompile to sure about required fields really exists):

sg.class(从反编译到确定必填字段确实存在)

private static Map c = new HashMap();
private static Map d = new HashMap();
private static Map e = new HashMap();
private static Map f = new HashMap();
private static Map g = new HashMap();
public static HashMap a = new LinkedHashMap();

采纳答案by Luke Woodward

Sorry, I can't reproduce this one.

抱歉,我无法重现这个。

Here's the full source code that I ran:

这是我运行的完整源代码:

import java.lang.reflect.*;
import java.util.*;

@SuppressWarnings("unchecked")
public class ReflectionTest {

    private static Object getPrivateStatic(Class clazz, String f) throws Exception {
        Field field = clazz.getDeclaredField(f);
        field.setAccessible(true);
        return field.get(null);
    }

    private static void a(Class paramClass, String paramString, int paramInt) {
        try {
            ((Map) getPrivateStatic(sg.class, "c")).put(paramString, paramClass);
            //...
        } catch (Exception exc) {
            exc.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
        a(String.class, "test", 0);
        sg.printC();
    }
}

class sg {
    private static Map c = new HashMap();
    private static Map d = new HashMap();
    private static Map e = new HashMap();
    private static Map f = new HashMap();
    private static Map g = new HashMap();
    public static HashMap a = new LinkedHashMap();

    public static void printC() {
        System.out.println(c);
    }
}

This was the output I got when I ran it:

这是我运行时得到的输出:

{test=class java.lang.String}

Given that you haven't specified the full decompiled source of the sgclass, I can only guess at a couple of things that may have happened:

鉴于您尚未指定sg该类的完整反编译源,我只能猜测可能发生的一些事情:

  • There is more than one class named sg, your code is using one of them but your decompiled output comes from a different one.
  • The fields exist within an inner class inside sg.
  • 有多个名为 的类sg,您的代码正在使用其中一个类,但您的反编译输出来自不同的类。
  • 这些字段存在于 内部的一个内部类中sg

EDIT: the class sgyou linked to below appears to contain a static field c, and contains no inner class, so I would expect to be able to use reflection to access this field. I cannot use your sgclass with the ReflectionTestclass I wrote above because it depends on numerous other classes with obfuscated names such as xk.

编辑sg您在下面链接到的类似乎包含一个静态字段c,并且不包含内部类,因此我希望能够使用反射来访问该字段。我不能将你的sg类与ReflectionTest我上面写的类一起使用,因为它依赖于许多其他带有混淆名称的类,例如xk.

I can only conclude that you have some confusion about exactly which class you are attempting to access the field cfrom. I suggest altering your getPrivateStaticmethod to the following, which may provide a more helpful error message, including the name of the class and all of the fields within it:

我只能得出结论,您对尝试c从哪个类访问该字段有一些困惑。我建议将您的getPrivateStatic方法更改为以下内容,这可能会提供更有用的错误消息,包括类的名称和其中的所有字段:

    private static Object getPrivateStatic(Class clazz, String f) throws Exception {
        try {
            Field field = clazz.getDeclaredField(f);
            field.setAccessible(true);
            return field.get(null);
        }
        catch (NoSuchFieldException e) {
            // Throw a more helpful exception.
            throw new NoSuchFieldException(
                "Could not find field named '" + f + "' in class '" + clazz +
                "'.  All fields: " + Arrays.asList(clazz.getDeclaredFields()));
        }
    }

回答by Sebastian

You are trying to get the field of the object null. See documentation on Field.get(Object)

您正在尝试将对象的字段设为 null。请参阅有关Field.get(Object) 的文档

You need to provide an object to get its field content. Or you need to provide a class to get a static fields content.

您需要提供一个对象来获取其字段内容。或者您需要提供一个类来获取静态字段内容。

So you should write the following:

所以你应该写以下内容:

private static Object getPrivateStatic(Class clazz, String f) throws Exception {
  Field field = clazz.getDeclaredField(f);
  field.setAccessible(true);
  return field.get(clazz);
}

btw. It is not considered good programming style to use reflection in production code since it e.g. makes refactoring problematic.

顺便提一句。在生产代码中使用反射不被认为是好的编程风格,因为它例如使重构有问题。

If you still need to use reflection (or are not working on production-code), use a framework for this kind of stuff (accessing private static field). With e.g. PrivilegedAccessorthis method would be a 1-liner:

如果您仍然需要使用反射(或不在生产代码上工作),请使用此类内容的框架(访问私有静态字段)。例如,使用PrivilegedAccessor,此方法将是 1-liner:

PA.getValue(clazz, f);