Introduction to JSR-275: Measures and Units

New API specification removes uncertainty from programming with physical measurements

Because Java is a strongly typed language, the compiler can usually detect when you make a mistake regarding the kind of input or output a method expects. But in developing programs that involve physical measurements, programmers working together still often face uncertainty. Is the temperature stated in Fahrenheit or Celsius? Is the speed in miles per hour or meters per second? Coding standards can somewhat alleviate this uncertainty, but only within a single organization. In this article, you'll read how JSR 275: Measures and Units delivers a general solution to this thorny issue.

Recently, working on an important customer project, I assumed that because all latitude and longitude data was entered in degrees, our projection routine expected degrees as well. Not true! The problem didn't manifest itself until late in the project life cycle, when we discovered that screen positions were way off base. A thorough review revealed that half our code dealt with radians and the other half with degrees. As co-spec lead of JSR 275: Measures and Units, I couldn't help but smile. I knew that this kind of problem would soon be a thing of the past.

A brief history of JSR 275
The story of JSR 275 began many years ago with JSR 108: Units API. JSR 108 dealt exclusively with units and was withdrawn by the spec lead for personal reasons. Unhappy about this abrupt termination, the expert group decided to start a new JSR with even wider goals in mind. Units were almost always associated with quantities, and providing only units and unit conversions was too limited. Also, they felt that new features in Java SE 5, such as annotations or parameterized types, could be taken advantage of without compromising performance. (The annotations road later proved to be impractical.) JSR 275 was approved in 2005, the first early draft review took place in July 2007, and the final draft is scheduled for early 2008.

Developers who work with physical quantities (in scientific, engineering, medical and manufacturing domains, for example) need to be able to handle measurements of those quantities in their programs. Inadequate models of physical measurements can lead to significant programmatic errors. In particular, the practice of modeling a measure as a simple number with no regard to the units it represents creates fragile code. Another developer or another part of the code might misinterpret the number as representing a different unit of measurement. For example, it might be unclear whether a person's weight is expressed in pounds, kilograms, or stone. The issue is difficult to solve through testing and has already cost millions of dollars to society worldwide. (NASA lost a $125 million Mars orbiter because a Lockheed Martin engineering team used English units of measurement while the agency's team used the more conventional metric system for a key spacecraft operation.)

Developers must either use inadequate models of measurements or create their own solutions. A standard solution can be safer, save development time for domain-specific work, and -- most important -- make code more readable and less error-prone. JSR 275 establishes such a framework for Java developers.

A simple framework

The Java namespace for JSR 275 is javax.measure, with one abstract class, Measure, and one interface, Measurable. A Measure is basically the product of a numerical value and a unit, such as "7.2 liters" or "24 hours," whereas Measurable identifies quantities capable of being measured, such as "altitude" or "delay."

Listing 1 shows how this is represented in Java terms (assuming a static import of the SI.* and NonSI.* units members).

Listing 1. Measure and Measurable

 Measure<Double, Volume> v = Measure.valueOf(7.2, LITER);
Measure<Integer, Duration> d = Measure.valueOf(24, HOUR);
class Altitude implements Measurable<Length> { ... }
class Delay implements Measurable<Duration> { ... }

I'll go into detail about units and class parameterization later in this article. Suffice it to say now that primitive types such as int and double representing quantities arguments can be replaced by Measure or Measurable. Consider the legacy code in Listing 2.

Listing 2. Legacy code

 class Person {
    void setWeight(double weight);

Should the weight be in pounds or kilograms? Measurable leaves no room for error, as shown in Listing 3.

Listing 3. No room for error

 class Person {
    void setWeight(Measurable<Mass> weight);

Not only is the interface cleaner (weight must be of type Mass), but there's also no confusion about the unit.

In Listing 4, the last statement results in a compile-time error, because weight is of type Mass and requires a unit of mass.

Listing 4. Unit mismatch causing compile-time error

double weightInKg = weight.doubleValue(KILOGRAM);
double weightInLb = weight.doubleValue(POUND);
double wrong = weight.doubleValue(LITER); // Compile Error!
1 2 3 4 Page 1
Page 1 of 4