2010-10-12 3 views
0

У меня есть два объекта разных классов, которые разделяют некоторые поля с тем же именем и типом. Эти два объекта не связаны друг с другом. У меня нет возможности создать интерфейс или родительский класс.Сравнение полей двух несвязанных объектов

Теперь я хочу сравнить эти общие поля, и насколько я знаю, это должно быть возможно с помощью отражения.

Эти шаги, я написал для такого метода сравнения:

Field[] inputFields = input.getClass().getDeclaredFields(); 
for (Field field : inputFields) { 
    log.info(field.getName() + " : " + field.getType()); 
} 

Там будет объект под названием database, к которому это полях inputFields сравниваются.

К сожалению, я не знаю, как получить значение моих полей. У тебя есть какие-то намеки?


Хорошо, с field.get(input) я получил значение сейчас, но, возможно, я был неправ, и что это не то, что мне нужно. На самом деле, я хочу сравнить это поле с другим, поэтому мне нужно вызвать метод equals в этом поле. Но сначала я должен отдать его в соответствующий класс. Так что-то вроде ((field.getClass()) field).equals(...), что сработает?

+1

Почему вы используете отражение? Не проще ли было бы написать метод, который взял оба объекта в качестве аргументов и сравнил значения полей (при условии, что есть геттеры)? – pablochan

+0

Да, но это было бы довольно утомительно. – 2010-10-12 09:42:29

+1

И используя отражение нет? Если, конечно, вы не знаете, что типы и/или имена этих полей будут изменены. – pablochan

ответ

2

Я думаю, что вы ищете Field.get():

for (Field field : inputFields) { 
    log.info(field.getName() + " : " 
      + field.getType() + " = " 
      + field.get(input); 
} 
0

Проверить dedicated chapter из Java учебник Солнца. This page отвечает на ваш конкретный вопрос на примере.

0

Вот решение этой проблемы, утилита класс называется FieldHelper, который имеет метод

Map<String, Object[]> properties = 
    FieldHelper.getCommonProperties(Object a, Object b) 

Возвращенная карта имеет имя поля как ключ и массив из двух значений поля в качестве значения:

public final class FieldHelper{ 

    private FieldHelper(){} 

    private static final Map<Class<?>, Map<String, PropertyDescriptor>> cache = 
     new HashMap<Class<?>, Map<String, PropertyDescriptor>>(); 

    /** 
    * Return a Map of field names to {@link PropertyDescriptor} objects for a 
    * given bean. 
    */ 
    public static Map<String, PropertyDescriptor> getBeanProperties(final Object o){ 

     try{ 
      final Class<?> clazz = o.getClass(); 
      Map<String, PropertyDescriptor> descriptors; 
      if(cache.containsKey(clazz)){ 
       descriptors = cache.get(clazz); 
      } else{ 
       final BeanInfo beanInfo = 
        Introspector.getBeanInfo(clazz, Object.class); 
       descriptors = new TreeMap<String, PropertyDescriptor>(); 
       for(final PropertyDescriptor pd : beanInfo.getPropertyDescriptors()){ 
        descriptors.put(pd.getName(), pd); 
       } 
       cache.put(clazz, 
        new TreeMap<String, PropertyDescriptor>(descriptors)); 
      } 
      final Map<String, PropertyDescriptor> beanProperties = descriptors; 
      return beanProperties; 

     } catch(final IntrospectionException e){ 
      throw new IllegalStateException("Can't get bean metadata", e); 
     } 
    } 

    /** 
    * Return a Map of all field names and their respective values that two 
    * objects have in common. Warning: the field values can be of different 
    * types. 
    */ 
    public static Map<String, Object[]> getCommonProperties(final Object a, 
     final Object b){ 
     final Map<String, PropertyDescriptor> aProps = getBeanProperties(a); 
     final Map<String, PropertyDescriptor> bProps = getBeanProperties(b); 
     final Set<String> aKeys = aProps.keySet(); 
     final Set<String> bKeys = bProps.keySet(); 
     aKeys.retainAll(bKeys); 
     bKeys.retainAll(aKeys); 
     final Map<String, Object[]> map = new TreeMap<String, Object[]>(); 

     for(final String propertyName : aKeys){ 
      final Object aVal = getPropertyValue(a, aProps.get(propertyName)); 
      final Object bVal = getPropertyValue(b, bProps.get(propertyName)); 
      map.put(propertyName, new Object[] { aVal, bVal }); 
     } 
     return map; 
    } 

    /** 
    * Return the value of a bean property, given the bean and the {@link PropertyDescriptor}. 
    */ 
    private static Object getPropertyValue(final Object a, 
     final PropertyDescriptor propertyDescriptor){ 
     try{ 
      return propertyDescriptor.getReadMethod().invoke(a); 
     } catch(final IllegalArgumentException e){ 
      throw new IllegalStateException("Bad method arguments", e); 
     } catch(final IllegalAccessException e){ 
      throw new IllegalStateException("Can't access method", e); 
     } catch(final InvocationTargetException e){ 
      throw new IllegalStateException("Invocation error", e); 
     } 
    } 

Код проверки:

public static void main(final String[] args){ 
    class Foo{ 
     private String abc = "abc"; 
     private String defy = "defy"; 
     private String ghi = "ghi"; 
     private String jkl = "jkl"; 
     // stripped getters and setters 
     // they must be there for this to work 
    } 
    class Bar{ 
     private Boolean abc = true; 
     private Integer def = 3; 
     private String ghix = "ghix3"; 
     private Date jkl = new Date(); 
     // stripped getters and setters 
     // they must be there for this to work 
    } 
    final Map<String, Object[]> properties = 
     getCommonProperties(new Foo(), new Bar()); 
    for(final Entry<String, Object[]> entry : properties.entrySet()){ 
     System.out.println("Field: " + entry.getKey() + ", value a: " 
      + entry.getValue()[0] + ", value b: " + entry.getValue()[1]); 
    } 
} 

Выход:

поле: азбука, значение а: азбука, значение б: истинно
поле: JKL, значение: с JKL, значение б: Вт 12 октября 14:03:31 CEST 2010

Примечание: этот код фактически не читает поля, он следует за соглашением java bean и вместо этого использует геттеры. Было бы легко переписать его для использования полей, но я бы посоветовал это сделать.

Смежные вопросы