【问题标题】:NoSuchFieldException when field exists字段存在时出现 NoSuchFieldException
【发布时间】:2013-03-14 21:56:49
【问题描述】:

我在尝试运行以下方法时收到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); }

错误在线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;

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

【问题讨论】:

  • 你的应用程序崩溃了吗?

标签: java reflection


【解决方案1】:

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

【讨论】:

  • 即使在使用 getDeclaredField 而不是 getField 之后,我仍然收到此错误:- 无法访问带有修饰符“private”的类成员
  • 哦,明白了。我需要使用 setAccessible(true)
  • 即使在使用 getDeclaredField() 时,我也会收到 NoSuchFieldException,即使在使用 setAccessible(true) 后也会出现“具有私人访问权限”错误。 示例 1Field fieldy = rootElement.getClass().getDeclaredField("name"); 抛出 NoSuchFieldException。但是Field[] fields = rootElement.getClass().getDeclaredFields(); 允许我遍历字段,当我调用field.getName() 时,它返回“名称”。那么有什么关系呢?
  • 已解决:看来我必须使用 try/catch 进行包装
  • @JoeFlack 用try/catch 包围如何解决任何问题?无论如何都会抛出异常,然后你在catch 中做什么来正确获取存在但以某种方式抛出NoSuchFieldException 的字段?
【解决方案2】:

根据javadoc,Class.getField()“返回一个Field对象,它反映了这个Class对象所代表的类或接口的指定公共成员字段”。 如果您想访问非公共字段,请使用 getDeclaredField()

【讨论】:

    【解决方案3】:

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

    1. 使用 getDeclaredField() 代替 getField():
            String propertyName = "test";
            Class.forName(this.getClass().getName()).getDeclaredField(propertyName);
    
    1. "HelloWorld" 替换为您的班级名称:
            String propertyName = "name";
            HelloWorld.class.getDeclaredField(propertyName);
    

    如果要获取列的注解长度:

    HelloWorld.class.getDeclaredField(propertyName).getAnnotation(Column.class).length();
    

    【讨论】:

      【解决方案4】:

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

      【讨论】:

      • 非常感谢。我的班级也变得模糊不清。我不得不禁用minifyEnabled 标志以防止它发生。
      【解决方案5】:

      我是根据标题来回答这个问题的。我在我的 Android 项目中遇到了同样的错误 (NoSuchFieldException),但原因不同。

      所以对于其他来这里的人来说,这个错误也可能是由于 Android Studio 中的缓存不同步造成的。转到 文件 > 使缓存无效/重新启动...

      另见this

      【讨论】:

        【解决方案6】:

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

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

        String propertyName = "foo";
        yourClass.getClass().getSuperClass().getDeclaredField(propertyName);
        

        【讨论】:

          【解决方案7】:

          很高兴知道...如果您的班级有 @Configuration,则 getDeclaredFields() 将不包含您的字段。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-11-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-09-06
            相关资源
            最近更新 更多