Type-Specific Specializations of Key Interfaces (Properties and Bindings) (JavaFX 2)

We did not emphasize this fact in the last section because we believe its omission does not hurt the explanations there, but except for Observable and InvalidationListener, the rest of the interfaces are generic interfaces with a type parameter <T>. In this section we examine how these generic interfaces are specialized to the specific types of interest: Boolean, Integer, Long, Float, Double, String, and Object. We also examine some of the abstract and concrete classes of the framework and explore typical usage scenarios of each class.

A Common Theme for Type-Specific Interfaces

Although the generic interfaces are not all specialized in exactly the same way, a common theme exists:

• The Boolean type is specialized directly.

• The Integer, Long, Float, and Double types are specialized through the Number supertype.

• The String type is specialized through the Object type.

This theme exists in the type-specific specializations of all the key interfaces. As an example, we examine the subinterfaces of the ObservableValue<T> interface:

• ObservableBooleanValue extends ObservableValue<Boolean>, and it offers one additional method.

tmpA-119_thumb


• ObservableNumberValue extends ObservableValue<Number>, and it offers four additional methods.

tmpA-120_thumb

• ObservableObjectValue<T> extends ObservableValue<t>, and it offers one additional method.

tmpA-121_thumb

• ObservableIntegerValue, ObservableLongValue, ObservableFloatValue, and ObservableDoubleValue extend ObservableNumberValue and each offers an additional get() method that returns the appropriate primitive type value.

• ObservableStringValue extends ObservableObjectValue<String> and inherits its get() method that returns String.

Notice that the get() method that we have been using in the examples is defined in the type-specific ObservableValue subinterfaces. A similar examination reveals that the set() method that we have been using in the examples is defined in the type-specific WritableValue subinterfaces.

A practical consequence of this derivation hierarchy is that any numerical property can call bind() on any other numerical property or binding. Indeed, the signature of the bind() method on any numerical property is

tmpA-122_thumb

and any numerical property and binding is assignable to the generic parameter type. The program in Listing 3-2 shows that any numerical properties of different specific types can be bound to each other.

Listing 3-4. NumericPropertiesExample.java

NumericPropertiesExample.java

 

 

 

 

NumericPropertiesExample.java

In this example we created four numeric properties and bound them into a chain in decreasing size to demonstrate that the bindings work as expected. We then reversed the order of the chain and set the double property’s value to a number that would overflow the integer property to highlight the fact that even though you can bind different sizes of numeric properties together, when the value of the dependent property is outside the range of the binding property, normal Java numeric conversion applies.

When we run the program in Listing 3-4, the following is printed to the console:

tmpA-125_thumb

 

 

 

tmpA-126_thumb

Commonly Used Classes

We now give a survey of the content of the four packages javafx.beans, javafx.beans.binding, javafx.beans.property, and javafx.beans.value. In this section, "the SimpleIntegerProperty series of classes" refers to the classes extrapolated over the Boolean, Integer, Long, Float, Double, String, and Object types. Therefore what is said also applies to SimpleBooleanProperty, and so on.

• The most often used classes in the JavaFX 2.0 properties and bindings framework are the SimpleIntegerProperty series of classes. They provide all the functionalities of the Property interface including lazy evaluation. They are used in all the examples of this topic up to this point.

• Another set of concrete classes in the JavaFX 2.0 properties and bindings framework is the ReadOnlyIntegerWrapper series of classes. These classes implement the Property interface but also have a getReadOnlyProperty() method that returns a ReadOnlyProperty that is synchronized with the main Property. They are very handy to use when you need a full-blown Property for the implementation of a component but you only want to hand out a ReadOnlyProperty to the client of the component.

• The IntegerPropertyBase series of abstract classes can be extended to provide implementations of full Property classes, although in practice the SimpleIntegerProperty series of classes is easier to use. The only abstract methods in the IntegerPropertyBase series of classes are getBean() and getName().

• The ReadOnlyIntegerPropertyBase series of abstract classes can be extended to provide implementations of ReadOnlyProperty classes. This is rarely necessary. The only abstract methods in the ReadOnlyIntegerPropertyBase series of classes are get(), getBean(), and getName().

• The WeakInvalidationListener and WeakChangeListener classes can be used to wrap InvalidationListener and ChangeListener instances before addListener() is called. They hold weak references of the wrapped listener instances. As long as you hold a reference to the wrapped listener on your side, the weak references will be kept alive and you will receive events. When you are done with the wrapped listener and have unreferenced it from your side, the weak references will be eligible for garbage collection and later garbage collected. All the JavaFX 2.0 properties and bindings framework Observable objects know how to clean up a weak listener after its weak reference has been garbage collected. This prevents memory leaks when the listeners are not removed after use.

That covers all the JavaFX 2.0 properties and bindings API that reside in the javafx.beans, javafx.beans.property, and javafx.beans.value packages and some but not all of the APIs in the javafx.beans.binding package. The remaining classes of the javafx.beans.binding package are APIs that help you to create new bindings out of existing properties and bindings. That is the focus of the next section.

Next post:

Previous post: