This time, I would like to explain how to detect that a property has been changed by using the standard Java API PropertyChangeListener
.
The process of detecting events is well known in Java GUI applications such as SWT, Swing, and AWT, but even ordinary Java classes have a mechanism to detect events whose properties have changed.
Item.java
package com.example.demo;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
public class Item {
private int price;
//★ Point 1
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
//★ Point 2
public void addPropertyChangeListener(PropertyChangeListener listener) {
this.pcs.addPropertyChangeListener(listener);
}
//★ Point 3
public void removePropertyChangeListener(PropertyChangeListener listener) {
this.pcs.removePropertyChangeListener(listener);
}
public int getPrice() {
return price;
}
//★ Point 4
public void setPrice(int price) {
int oldPrice = this.price;
this.price = price;
this.pcs.firePropertyChange("price", oldPrice, price);
}
// generated by eclipse
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Item [price=");
builder.append(price);
builder.append("]");
return builder.toString();
}
}
** ★ Point 1 **
Create an instance of java.beans.PropertyChangeSupport
and define it as a field.
The constructor argument of PropertyChangeSupport
specifies this
because it is the object that originated (detected) the event.
** ★ Point 2 **
Implement the method to add java.beans.PropertyChangeListener
to PropertyChangeSupport
defined in ★ Point 1.
** ★ Point 3 **
Implement a method that removes java.beans.PropertyChangeListener
from PropertyChangeSupport
.
Please think that ★ Point 2 and ★ Point 3 are the usual things to implement as a set.
** ★ Point 4 **
Raise a property change event with the firePropertyChange
method of PropertyChangeSupport
.
Person.java
package com.example.demo;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
public class Person {
private String name;
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
public void addPropertyChangeListener(PropertyChangeListener listener) {
this.pcs.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
this.pcs.removePropertyChangeListener(listener);
}
public String getName() {
return name;
}
public void setName(String name) {
String oldName = this.name;
this.name = name;
this.pcs.firePropertyChange("name", oldName, name);
}
// generated by eclipse
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Person [name=");
builder.append(name);
builder.append("]");
return builder.toString();
}
}
DemoListener.java
package com.example.demo;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
//★ Point 5
public class DemoListener implements PropertyChangeListener {
//★ Point 6
@Override
public void propertyChange(PropertyChangeEvent evt) {
//★ Point 7
Object eventTriggerObject = evt.getSource();
String propertyName = evt.getPropertyName();
//★ Point 8
if (Item.class.isInstance(eventTriggerObject)) {
if ("price".equals(propertyName)) {
//★ Point 9
Integer oldValue = (Integer) evt.getOldValue();
Integer newValue = (Integer) evt.getNewValue();
System.out.println("[Item.price] oldValue:" + oldValue + " -> newValue:" + newValue);
}
} else if (Person.class.isInstance(eventTriggerObject)) {
if ("name".equals(propertyName)) {
String oldValue = (String) evt.getOldValue();
String newValue = (String) evt.getNewValue();
System.out.println("[Person.name] oldValue:" + oldValue + " -> newValue:" + newValue);
}
}
}
}
** ★ Point 5 **
Defines a class that implements the java.beans.PropertyChangeListener
interface.
** ★ Point 6 **
Implement the process of handling property change events by overriding the propertyChange
method.
** ★ Point 7 **
Get the object from which the change event originated with the getSource ()
method of java.beans.PropertyChangeEvent
.
Also, the changed property can be specified by using the getPropertyName ()
method because the property name can be obtained.
** ★ Point 8 **
This time, listeners are registered in both the ʻItem class and the
Person` class, so it is necessary to determine which instance is the source.
** ★ Point 9 **
The value before the property change is obtained by the getOldValue ()
method, and the value after the change is obtained by the getNewValue ()
method.
The return value is ʻObject`, so you need to cast it according to the data type of the property.
App.java
package com.example.demo;
public class App {
public static void main(String[] args) {
Item item = new Item();
System.out.println(item);
item.setPrice(500);
System.out.println(item);
DemoListener demoListener = new DemoListener();
item.addPropertyChangeListener(demoListener);
item.setPrice(700);
item.setPrice(1000);
Person person = new Person();
System.out.println(person);
person.setName("Taro");
System.out.println(person);
person.addPropertyChangeListener(demoListener);
person.setName("5zm");
person.setName("Yamada");
item.removePropertyChangeListener(demoListener);
person.removePropertyChangeListener(demoListener);
}
}
Item [price=0]
Item [price=500]
[Item.price] oldValue:500 -> newValue:700
[Item.price] oldValue:700 -> newValue:1000
Person [name=null]
Person [name=Taro]
[Person.name] oldValue:Taro -> newValue:5zm
[Person.name] oldValue:5zm -> newValue:Yamada
Before adding a listener with ʻaddPropertyChangeListener, setting a value with
setter` does nothing, and after adding a listener, you can see that the changed content is detected by the listener.
This time, I explained how to detect that a property has been changed by using the standard Java API PropertyChangeListener
.
By using PropertyChangeListener
, you can easily try event processing without preparing a special library.