使用反射比较字段值

时间:2012-11-21 15:01:50

标签: java reflection field

我试图以通用方式比较两个不同对象的字段值。我有一个函数(如下所示),它接收两个对象,然后获取字段,然后比较循环中的字段,如果它们不相同,则将字段添加到列表中 - 这是正确的方法吗?< / p>

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() - 我知道没有这样的方法,但也许有另一种方式???

3 个答案:

答案 0 :(得分:11)

你可以查看一下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))目前,您实际上是在比较字段实例而不是值。

答案 1 :(得分:3)

commons-beanutils等库可以帮助您比较bean属性(getter返回的值)而不是比较字段值。

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

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

答案 2 :(得分:0)

//如果要具有某些字段,而不是所有字段,请使用此字段。

  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;
}