JavaBeans PropertyChangeSupport Trick
I’ve always written bound properties like this:
public class Rect {
private PropertyChangeSupport changes = new PropertyChangeSupport(this);
private int width;
public void setWidth(int width) {
int old = this.width;
this.width = width;
changes.firePropertyChange("width", old, width);
}
}
I just realized that the 3-line setWidth(...) method can be compressed to a single line:
public void setWidth(int width) {
changes.firePropertyChange("width", this.width, this.width = width);
}
It seems like this might reduce a significant amount of boilerplate code for some types of apps.
UPDATE
As pointed out in the comments, for non-primitive properties, null values (both old and new) will trigger unwanted events. Although generally harmless, firing too many events can cause significant performance problems, particularly if you trigger repainting in the GUI for properties that didn’t really change.
So you might want to do this:
public void setName(String name) {
if (this.name != null || name != null) {
changes.firePropertyChange("name", this.name, this.name = name);
}
}
Or this, depending on your style:
public void setName(String name) {
if (this.name == null && name == null) {
return;
}
changes.firePropertyChange("name", this.name, this.name = name);
}
It’s a bit dense, but I like to use this pattern too. One benefit is that you can easily use your favourite IDE’s template mechanism to generate setters, because you don’t have to declare local variables.
And neither is correct since you don’t check that the new value is different from the old one (hence the property *change* listener).
@Kirill: A programmer does not need the check if the values are different. This is part of the implementation. E.g. for Objects:
public void firePropertyChange( String propertyName, Object oldValue, Object newValue )
{
if ( oldValue != null && newValue != null && oldValue.equals( newValue ) )
{
return;
}
firePropertyChange( new PropertyChangeEvent( source, propertyName, oldValue, newValue ) );
}
As a side note: It is very important to have a valid equals() method on Objects! So StringBuffer is a difficult one.
@Kirill, that’s really not correct. PropertyChangeSupport does this for you. If my code included comparisons between old and new value, that would actually degrade, rather than improve performance, because PropertyChangeSupport would then perform a redundant comparison.
My bad. I’m so used to the internal Swing code not using PropertyChangeSupport that i’ve missed that part.
No, there is a bug…
firePropertyChange(’propertyName’, null, null)
This will fire a non-change
–Danno
I think the most compact way is to use AOP to handle this problem : )
Yeah I use it all the time too. It doesn’t provide native property support but as a shorthand notation it’s great.
An even more elegant comparison to bumper the call with the direct comparison…
public void setName( name) {
if (this.name != name) changes.firePropertyChange(”name”, this.name, this.name = name);
}
This will handle the null/null case as well as the same-string case. The PropertyChangeSupport will handle the equivalent string case via a call to .equals(Object)
This is neat, i thought that methods first collected all the arguments references into an intermediary structure and called the method “atomically”. Is this specified by the Java Virtual Machine? Can it be JVM dependent?
On second thought even so this makes sense, since what is passes is a “reference”. Cool anyway.
Also i don’t think direct comparison will work for non final and non cached classes. Just IMNHO.
And classes that redefine the == operator. This means Strings and … BigInteger, Double …?
I must say that this project reCaptcha is very, very interesting. Finally a positive justification for spam.
…
Put down those pitchforks, i’m leaving.
I made a quick post at my blog on how to automate adding these things in eclipse with this technique:
http://www.weheartcode.com/2008/04/29/easily-add-propertychangesupport-to-beans-in-eclipse/