Как собрать все свойства объекта, который был обновлен?

#java

#java

Вопрос:

Я вроде как новичок в Java, поэтому приношу свои извинения, если вы находите этот вопрос бессмысленным. Просто хочу спросить, возможно ли собрать все свойства объекта, особенно те, которые больше не являются значениями по умолчанию. Например, компонент, для некоторых свойств которого были установлены новые значения, как я смогу получить те свойства, которые были обновлены, учитывая только объект с новыми значениями в нем.. Или есть способ собрать все методы установки, которые были вызваны для данного компонента?

Комментарии:

1. Есть ли у вас один конкретный компонент, в котором вы хотите обнаруживать значения атрибутов, отличных от значений по умолчанию, и воздействовать на них; ИЛИ вам нужно сделать это «в общем виде» для многих компонентов? Подход, который я бы выбрал, был бы другим, потому что общее решение намного сложнее.

Ответ №1:

Вы можете зарегистрировать java.beans.PropertyChangeListener в своем объекте и запускать событие при вызове каждого установщика. Это выглядело бы как:

 public class Foo {
   // some field here
   private PropertyChangeListener listener;

   public void setBar(String bar) {
      this.bar = bar;
      if (listener != null) {
         listener.fireEvent(..);
      }
   }
   // etc setters and getters

   // setter for the listener
   // (instead of a single listener, you may want a collection of listeners)
}
  

Затем в прослушивателе вы можете сохранить все изменения в коллекции, например.

Комментарии:

1. 1 за стандартный способ (хотя это чертовски сложно)

2. насколько я понял, отслеживание изменений во время их возникновения не было вопросом

3. нет, но он хочет знать, какие свойства были изменены. Вот почему при каждом изменении он может добавлять измененные свойства в коллекцию (мой последний абзац)

4. хм… это сбор тех, которые были изменены после того, как он / она начнет прослушивание. Требованием было «те свойства, которые были обновлены, предоставили только объект с новыми значениями в нем». — это до того, как у него появится шанс начать прослушивание

5. Я предполагаю, что когда он создает объект, он также может зарегистрировать прослушиватель.

Ответ №2:

Для любого «компонента», то есть класса, работающего по спецификации компонента, вы можете использовать самоанализ / отражение, что-то вроде:

 public static class MyBean {

    String myName;

    public MyBean() {
       this(null);
    }

    public MyBean(String name) {
        setName(name);
    }

    public String getName() {
        return myName;
    }

    public void setName(String name) {
        this.myName = name;
    }
}

public void testBeanProperties() throws Exception {
    Object bean = new MyBean("myName");
    compareProperties(bean);
}

private void compareProperties(Object bean) throws Exception {
    BeanInfo info = Introspector.getBeanInfo(bean.getClass()); 
    Object defaultInstance = bean.getClass().newInstance();
    PropertyDescriptor[] descriptors = info.getPropertyDescriptors();
    for (PropertyDescriptor descriptor : descriptors) {
        Object defaultValue = getValue(defaultInstance, descriptor);
        Object myValue = getValue(bean, descriptor);
        if (!areEqual(myValue, defaultValue)) {
            System.out.println("default/changed: "   defaultValue   " / "   myValue );
        }
    }
}

public Object getValue(Object bean, PropertyDescriptor propertyDescriptor) throws Exception {
    Method getter = propertyDescriptor.getReadMethod();
    if (getter != null)
        return getter.invoke(bean, (Object[]) null);
    return null;
}
  

что касается ответов, связанных с PropertyChangeListener: это вариант, только если «компонент» действительно отправляет уведомление об изменении (что и должно быть, но это другая тема 🙂 Кроме того, он не может перехватить какие-либо свойства, установленные в конструкторе.

Комментарии:

1. это хороший способ отслеживать изменения, хотя он включает в себя создание нового объекта и отражение. в любом случае 1.

Ответ №3:

Для достижения этого не существует встроенного по умолчанию способа. Если я правильно понимаю, вы хотите собрать все свойства, которые были изменены в компоненте. Что-то вроде:

 MyBean bean = new MyBean();
bean.setName("john");
List modified = bean.getModifiedFields();
  

Как предложил Бозо, вы можете использовать PropertyChangeListener для запуска события при изменении свойства или, проще говоря:

 public class MyBean {
   private Map<String, Object> modifiedValuesMap = new HashMap<String, Object>();
   private String name;
   public void setName(String _name) {
     name = _name;
     modifiedValuesMap.put("name", _name);

   }      
   public Map<String, Object> getModifiedValues() {
     return modifiedValuesMap;
   }

}