【问题标题】:Comparing field values using reflection使用反射比较字段值
【发布时间】:2012-11-09 20:49:00
【问题描述】:

我正在尝试以通用方式比较两个不同对象的字段值。我有一个函数(见下文),它接受两个对象,然后获取字段,然后在循环中比较字段,如果字段不相同,则将字段添加到列表中 - 这是正确的方法吗?

public void compareFields(Object qa, Object qa4) throws FieldsNotEqualException
{

  Field[] qaFields = qa.getClass().getFields();
  Field[] qa4Fields = qa4.getClass().getFields();

  for(Field f:qaFields) 
  { 

    for(Field f4:qa4Fields)
    {
       if(f4.equals(f))
       {
           found = true;
           break;
       }
       else
       {
           continue;
       }
    }
  }

 if(!found)
 {
    report.add(/*some_formatted_string*/) //some global list 
    throw new FieldsNotEqualException();
 }
}

我在谷歌上搜索,发现 C# 有一个 PropertyInfo 类——Java 有类似的东西吗? 另外,有没有办法像f.getFieldValue()一样做-我知道没有这样的方法,但也许还有另一种方法???

【问题讨论】:

  • 字段属于类,值保存在实例中(如果不是静态的)。你到底想完成什么?
  • 好吧,我应该更清楚一点——我传入两个对象的两个实例——我试图比较 hibernate 返回的两个数据集(对象列表)——但我将它们传递给一次循环某个类的对象的一个​​实例,以将该实例的字段与其他实例进行比较
  • @JohH 如果您使用的是 Hibernate,这种方法可能不起作用 - Hibernate 在运行时修改对象内容,我不确定反射是否会起作用 - 它可能会起作用,但如果您遇到一些有趣的事情,它可能是 Hibernate 干扰了对象属性。
  • @RaviWallau 我认为 Hibernate 已经完成了对这些对象的干扰......我运行了一个查询,然后从 Hibernate 返回一个 List() 。如果我想以非通用方式执行此操作,我可以强制转换列表中的每个实例,然后比较值 - 但这将是很多可以通用完成的代码。
  • @JohH 如果您使用 IntelliJ,您可以自动生成 equals() 和 hashCode()。比起使用反射来比较数据,我更喜欢这些,因为反射不能限制将要比较的字段。

标签: java reflection field


【解决方案1】:

您可以查看 org.apache.commons.lang.builder.EqualsBuilder 如果您想逐个字段进行比较,这将为您省去很多麻烦。

org.apache.commons.lang.builder.EqualsBuilder.reflectionEquals(Object, Object)

如果您想自己比较字段,请查看java.lang.Class.getDeclaredFields(),它将为您提供所有字段,包括非公共字段。

要比较字段的值,请使用f.get(qa).equals(f.get(qa4)) 目前,您实际上是在比较字段实例而不是值。

【讨论】:

  • 当我需要比较值时,getDeclaredFields() 如何提供帮助?
  • @JonH 我稍微更新了我的答案。要点是您确实应该考虑使用通用库进行此比较。希望这会有所帮助。
  • 好的 - 我相信这是有效的 - 但我有一个简单的问题 - 所以 of.get(qa) 将获得字段“some_name”的值 - 所以我不必担心字段排序或确保是在比较同一个字段吗?
  • 假设这些是相同的类类型,字段顺序将是相同的。
【解决方案2】:

如果您想比较 bean 属性(getter 返回的值)而不是比较字段值,像 commons-beanutils 这样的库可以为您提供帮助。

但是,如果您想坚持使用普通反射,您应该:

  1. 使用Class.getDeclaredFields() 而不是Class.getFields(),因为后者只返回公共字段。
  2. 由于字段仅依赖于它们的类,因此您应该缓存结果并将字段保存在静态/实例变量中,而不是为每次比较调用 getDeclaredFields()
  3. 一旦您拥有该类的对象(例如o),为了获取该特定对象的某个字段f 的值,您需要调用:f.get(o)

【讨论】:

    【解决方案3】:

    // 如果你想要一些字段,而不是所有字段,那么使用这个。

      public boolean compareObject(Object object) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException 
    {
    
     String[] compareFields = { "fieldx", "fieldy","fieldz", "field15",
            "field19"}; // list of all we need 
    for(String s : compareFields) {
    Field field = DcrAttribute.class.getDeclaredField(s); // get a list of all fields for this class
        field.setAccessible(true);
        if(!field.get(this).equals(field.get(object))){  //if values are not equal          
        return true;    
        }       
    
        }
    
        return false;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多