使用 getDeclaredField() 且字段存在时出现 NoSuchFieldException
NoSuchFieldException when using getDeclaredField() and field exists
java.lang.NoSuchFieldException: c
at java.lang.Class.getDeclaredField(Unknown Source)
at ru.onlymc.OnlyMZ.CustomEntityType.getPrivateStatic(CustomEntityType.java:177)
方法:
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();
}
}
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();
您正试图让对象的字段为空。请参阅有关 Field.get(Object)
的文档
您需要提供一个对象来获取其字段内容。或者您需要提供一个 class 来获取静态字段内容。
所以你应该这样写:
private static Object getPrivateStatic(Class clazz, String f) throws Exception {
Field field = clazz.getDeclaredField(f);
field.setAccessible(true);
return field.get(clazz);
}
顺便说一句。在生产代码中使用反射不被认为是好的编程风格,因为它例如使重构成为问题。
如果您仍然需要使用反射(或不在生产代码上工作),请使用此类框架(访问私有静态字段)。例如PrivilegedAccessor 这个方法是 1-liner:
PA.getValue(clazz, f);
抱歉,我无法复制这个。
这是我 运行:
的完整源代码
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);
}
}
这是我 运行 时得到的输出:
{test=class java.lang.String}
鉴于您没有指定 sg
class 的完整反编译源,我只能猜测可能发生的几件事:
- 有多个 class 名为
sg
,您的代码正在使用其中一个,但您的反编译输出来自另一个。
- 字段存在于
sg
内的内部 class 中。
EDIT:您链接到下面的 class sg
似乎包含静态字段 c
,并且不包含内部 class,所以我希望能够使用反射来访问这个字段。我不能将你的 sg
class 与我在上面写的 ReflectionTest
class 一起使用,因为它依赖于许多其他 classes 具有混淆的名称,例如 xk
.
我只能得出这样的结论:您对您尝试从哪个 class 访问字段 c
感到有些困惑。我建议将您的 getPrivateStatic
方法更改为以下内容,这可能会提供更有用的错误消息,包括 class 的名称及其中的所有字段:
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()));
}
}
java.lang.NoSuchFieldException: c
at java.lang.Class.getDeclaredField(Unknown Source)
at ru.onlymc.OnlyMZ.CustomEntityType.getPrivateStatic(CustomEntityType.java:177)
方法:
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();
}
}
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();
您正试图让对象的字段为空。请参阅有关 Field.get(Object)
的文档您需要提供一个对象来获取其字段内容。或者您需要提供一个 class 来获取静态字段内容。
所以你应该这样写:
private static Object getPrivateStatic(Class clazz, String f) throws Exception {
Field field = clazz.getDeclaredField(f);
field.setAccessible(true);
return field.get(clazz);
}
顺便说一句。在生产代码中使用反射不被认为是好的编程风格,因为它例如使重构成为问题。
如果您仍然需要使用反射(或不在生产代码上工作),请使用此类框架(访问私有静态字段)。例如PrivilegedAccessor 这个方法是 1-liner:
PA.getValue(clazz, f);
抱歉,我无法复制这个。
这是我 运行:
的完整源代码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);
}
}
这是我 运行 时得到的输出:
{test=class java.lang.String}
鉴于您没有指定 sg
class 的完整反编译源,我只能猜测可能发生的几件事:
- 有多个 class 名为
sg
,您的代码正在使用其中一个,但您的反编译输出来自另一个。 - 字段存在于
sg
内的内部 class 中。
EDIT:您链接到下面的 class sg
似乎包含静态字段 c
,并且不包含内部 class,所以我希望能够使用反射来访问这个字段。我不能将你的 sg
class 与我在上面写的 ReflectionTest
class 一起使用,因为它依赖于许多其他 classes 具有混淆的名称,例如 xk
.
我只能得出这样的结论:您对您尝试从哪个 class 访问字段 c
感到有些困惑。我建议将您的 getPrivateStatic
方法更改为以下内容,这可能会提供更有用的错误消息,包括 class 的名称及其中的所有字段:
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()));
}
}