字段存在时为NoSuchFieldException

dre*_*ore 68 java reflection

java.lang.NoSuchFieldException试图运行以下方法时得到一个:

 public void getTimes(String specialty, String day) {
    ArrayList<Tutor> withSpec = new ArrayList<Tutor>();
    for (Tutor t : tutorList){
        try {
            Time startTime = (Time)t.getClass().getField(day + "Start").get(t);
        } catch (NoSuchFieldException | SecurityException | IllegalAccessException ex) Logger.getLogger(DBHandler.class.getName()).log(Level.SEVERE, null, ex); }
Run Code Online (Sandbox Code Playgroud)

错误就行了 Time startTime = (Time)t.getClass().getField(day + "Start").get(t);

我不明白这个错误,因为monStart是Tutor该类的一个字段:

Public class Tutor implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@NotNull
@Column(name = "tutorID")
private Integer tutorID;

.... 

@Column(name = "monStart")
@Temporal(TemporalType.TIME)
 Date monStart;
Run Code Online (Sandbox Code Playgroud)

我只是学习使用反射,所以我确定这是某种语法错误......

rge*_*man 149

getField方法只会找到该字段public.您将需要使用该getDeclaredField方法,它将找到直接在类上声明的任何字段,即使它不是public.

  • 哦,明白了.我需要使用setAccessible(true) (9认同)
  • @JoeFlack 周围的“try/catch”是如何解决任何问题的?无论如何都会抛出异常,然后你在“catch”中做什么来正确获取存在但以某种方式抛出“NoSuchFieldException”的字段? (3认同)
  • 即使使用`getDeclaredField()`,我也会收到`NoSuchFieldException`,即使使用`setAccessible(true)`之后,也有“具有私有访问”错误。**示例1 **:`Field fieldy = rootElement.getClass()。getDeclaredField(“ name”);`抛出`NoSuchFieldException`。但是执行Field [] fields = rootElement.getClass()。getDeclaredFields();可以使我遍历这些字段,当我调用field.getName()时,它返回“名称”。那怎么办? (2认同)
  • **已解决**:看起来我必须在 try/catch 中进行包装 (2认同)

Cos*_*atu 12

根据javadoc,Class.getField()"返回一个Field反映该Class对象所代表的类或接口的指定公共成员字段的对象".使用getDeclaredField()如果您要访问非公共领域.


Bri*_*cho 9

对于任何看到此问题但似乎仍无法解决问题的 Android 开发人员,请检查是否启用了 Proguard。如果是,则相关类可能被混淆了,您需要添加规则来防止这种情况发生。


小智 7

getClass().getField()问题的最佳解决方案是:

使用getDeclaredField()而不是getField()

1)  String propertyName = "test";
    Class.forName(this.getClass().getName()).getDeclaredField(propertyName);
Run Code Online (Sandbox Code Playgroud)

2)用您的班级名称替换"HelloWorld"

    String propertyName = "name";
    HelloWorld.class.getDeclaredField(propertyName)
Run Code Online (Sandbox Code Playgroud)

如果要获取列的注释长度

HelloWorld.class.getDeclaredField(propertyName).getAnnotation(Column.class).length()
Run Code Online (Sandbox Code Playgroud)


pay*_*yne 6

正如接受的答案中提到的,使用getDeclaredField可能会解决您的问题(如果该字段未声明为public)。

如果您仍然得到NoSuchFieldException,那么可能是因为该字段实际上位于超类中!确实,如果你的类extends是另一个类,那么你将无法通过该getDeclaredField方法获得继承的字段。以下是解决该问题的方法:

String propertyName = "foo";
yourClass.getClass().getSuperClass().getDeclaredField(propertyName);
Run Code Online (Sandbox Code Playgroud)