Wrapping Java Fields in Static Anonymous Inner Class Constants

First-class functions really are a nice thing. Joel Spolsky devoted a whole blog entry to them. Java, sadly, doesn’t have first-class functions. This lack can make itself annoyingly noticeable when you have a class with many properties, and you need to formulate constraints and rules for these properties.

Enter the Element

Consider the following simple example of a class Element with a single integer property width:

class Element {
	private int width;
	int getWidth() { return width; }
}

If you had to check that the sum of the widths across a given collection of elements stayed within a given limit, you might do something like the following:

class CheckConstraints {
	static boolean isWidthSumWithinLimit(final Iterable<Element> elements, final int limit) {
		int sum = 0;
		for (final Element e : elements) {
			sum += e.getWidth();
		}
		return sum <= limit;
	}
}

More Constraints – the Python Way

Simple enough. But then, of course, your requirements change, and your element gets an additional property height:

class Element {

	private int width;
	private int height;

	int getWidth() {
		return width;
	}

	int getHeight() {
		return height;
	}
}

And, inevitably, you need to check the same constraint for that new field. Conceptually, all you need to do in isWidthSumWithinLimit is to replace the one tiny little call to getWidth() with getHeight(). (And perhaps give the method a different name.) If you had first-class functions, extracting that call out of the method would be easy. In Python (which has first-class functions), our Element could look like this:

class Element:

    def __init__(self, width, height):
        self.width = width
        self.height = height

    def getWidth(self):
        return self.width

    def getHeight(self):
        return self.height

And the constraints could be checked in this way:

# the general sum checking case
def isSumWithinLimit(elements, getter, limit):
    return limit >= sum([getter(e) for e in elements])

# the special case for widths
def isWidthSumWithinLimit(elements, limit):
    return isSumWithinLimit(elements, Element.getWidth, limit)

# the special case for heights
def isHeightSumWithinLimit(elements, limit):
    return isSumWithinLimit(elements, Element.getHeight, limit)

I.e., we pass the Element functions Element.getWidth and Element.getHeight as the getter argument into the general isSumWithinLimit, where they are called as getter(e). And everything is well.

The Java Way: Anonymous Inner Classes

In principle, you can pass around functions in Java. You just have to take the detour of wrapping your function in an interface and passing instances of said interface around via anonymous inner classes. Following that route, the Java equivalent of the above Python code could look like the following:

First, we define the interface which, given an Element, lets us pick the value we are interested in:

interface IntGetter {
	Integer get(final Element e);
}

Then we define a general version of our sum constraint check using that interface:

	static boolean isSumWithinLimit(final Iterable<Element> elements, final IntGetter getter, final int limit) {
		int sum = 0;
		for (final Element e : elements) {
			sum += getter.get(e);
		}
		return sum <= limit;
	}

And finally, we define our two special cases for width and height using anonymous inner IntGetter instances:

	// ... the width
	static boolean isWidthSumWithinLimit(final Iterable<Element> elements, final int limit) {
		return isSumWithinLimit(elements, new IntGetter() {
			@Override
			public Integer get(final Element e) {
				return e.getWidth();
			}
		}, limit);
	}

	// ... and the height
	static boolean isHeightSumWithinLimit(final Iterable<Element> elements, final int limit) {
		return isSumWithinLimit(elements, new IntGetter() {
			@Override
			public Integer get(final Element e) {
				return e.getHeight();
			}
		}, limit);
	}

So the general isSumWithinLimit method can handle whatever field we can make accessible via an IntGetter. On the one hand, this helps the checking method concentrate on its core functionality of summing up numbers and comparing them to a limit. It no longer has to care about where those numbers come from. On the other hand, unfortunately, the code is horrendously long and verbose.

Extracting to Constants

It gets worse if you wanted to introduce more checks, such as the isEachWithinLimit check, which compares every element individually to a given limit. As with the sum check, we define a general case based using an IntGetter:

	static boolean isEachWithinLimit(final Iterable<Element> elements,
			final IntGetter getter, final int limit) {
		for (final Element e : elements) {
			if (getter.get(e) > limit)
				return false;
		}
		return true;
	}

And if we want to use that check for widths, we write a specialized check using an anonymous inner class:

	// the specific case for the width
	static boolean isEachWidthWithinLimit(final Iterable<Element> elements, final int limit) {
		return isEachWithinLimit(elements, new IntGetter() {
			@Override
			public Integer get(final Element e) {
				return e.getWidth();
			}
		}, limit);
	}
// ...

We find ourselves duplicating the anonymous width-specific IntGetter class. Consequently, for n properties and m constraints, our code’s verbosity could well be in O(n*m). As a simple remedy against both the bulkiness of the specialized check methods and the duplication of each specific getter class, we can extract the getter classes into static constants on the Element:

class Element {
	private int width;
	private int height;

	int getWidth() {
		return width;
	}

	int getHeight() {
		return height;
	}

	static IntGetter WIDTH = new IntGetter() {
		@Override
		public Integer get(final Element e) {
			return e.getWidth();
		}
	};

	static IntGetter HEIGHT = new IntGetter() {
		@Override
		public Integer get(final Element e) {
			return e.getHeight();
		}
	};
}

With these in place, we can formulate our various constraint checks a little less verbosely. The two general constraint checks don’t change, but the special cases do:

	// sum of widths
	static boolean isWidthSumWithinLimit(final Iterable<Element> elements,
			final int limit) {
		return isSumWithinLimit(elements, Element.WIDTH, limit);
	}

	// each width
	static boolean isEachWidthWithinLimit(final Iterable<Element> elements,
			final int limit) {
		return isEachWithinLimit(elements, Element.WIDTH, limit);
	}

	// sum of heights
	static boolean isHeightSumWithinLimit(final Iterable<Element> elements,
			final int limit) {
		return isSumWithinLimit(elements, Element.HEIGHT, limit);
	}

	// each height
	static boolean isEachHeightWithinLimit(final Iterable<Element> elements,
			final int limit) {
		return isEachWithinLimit(elements, Element.HEIGHT, limit);
	}

Finally, each case has been reduced to the one-liner it really should be – quite similar to the original Python example code.

When there’s more than just Elements

So far, the static anonymous inner class constants have given us something like first-class fields on Element. We can generalize the code to work with classes other than Element by making the IntGetter and the constraints generic with respect to the class on which they are called:

interface IntGetter<E> {
	Integer get(final E e);
}

The constants in Element don’t have to change much. They just have the type parameter added:

class Element {

	// ... snip ...

	static IntGetter<Element> WIDTH = new IntGetter<Element>() {
		@Override
		public Integer get(final Element e) {
			return e.getWidth();
		}
	};

	static IntGetter<Element> HEIGHT = new IntGetter<Element>() {
		@Override
		public Integer get(final Element e) {
			return e.getHeight();
		}
	};
}

And we have to generify the general checker methods to allow other types:

	// the general cases
	static <E> boolean isSumWithinLimit(final Iterable<E> elements,
			final IntGetter<E> getter, final int limit) {
		int sum = 0;
		for (final E e : elements) {
			sum += getter.get(e);
		}
		return sum <= limit;
	}

	static <E> boolean isEachWithinLimit(final Iterable<E> elements,
			final IntGetter<E> getter, final int limit) {
		for (final E e : elements) {
			if (getter.get(e) > limit)
				return false;
		}
		return true;
	}

Now, if we get a new class Thing with an integer property depth, we wrap depth in a static anonymous inner class constant:

class Thing {
	private int depth;

	static IntGetter<Thing> DEPTH = new IntGetter<Thing>() {
		@Override
		public Integer get(final Thing e) {
			return e.depth;
		}
	};
}

And without further changes, we can call all our constraint checks on things and their depths:

	static boolean isEachDepthWithinLimit(final Iterable<Thing> things,
			final int limit) {
		return isEachWithinLimit(things, Thing.LENGTH, limit);
	}

So, for the price of defining the static anonymous inner class constants, we can pass them around as fields. If you have few of these fields, and you have a lot of repetitive handling to do with them, using static anonymous inner class constants can help you elegantly reuse significant portions of the handler code.

Hidden below is the whole source for this small example along with a simple main class:

/**
 * Demonstration of simple Anonymous Inner Class Constants
 *
 * NB: Code does not reflect best practices with regard to packaging, etc.
 *
 * @author Hans Bering
 */
package simple.ex3;

import java.util.ArrayList;
import java.util.List;

interface IntGetter<E> {
	Integer get(final E e);
}

class Element {

	private final int width;
	private final int height;

	Element(final int width, final int height) {
		this.width = width;
		this.height = height;
	}

	int getWidth() {
		return width;
	}

	int getHeight() {
		return height;
	}

	static IntGetter<Element> WIDTH = new IntGetter<Element>() {
		@Override
		public Integer get(final Element e) {
			return e.getWidth();
		}
	};

	static IntGetter<Element> HEIGHT = new IntGetter<Element>() {
		@Override
		public Integer get(final Element e) {
			return e.getHeight();
		}
	};
}

class Thing {

	private final int length;

	Thing(final int length) {
		this.length = length;
	}

	static IntGetter<Thing> LENGTH = new IntGetter<Thing>() {
		@Override
		public Integer get(final Thing e) {
			return e.length;
		}
	};
}

class ConstraintChecker {

	static <E> boolean isSumWithinLimit(final Iterable<E> elements,
			final IntGetter<E> getter, final int limit) {
		int sum = 0;
		for (final E e : elements) {
			sum += getter.get(e);
		}
		return sum <= limit;
	}

	static <E> boolean isEachWithinLimit(final Iterable<E> elements,
			final IntGetter<E> getter, final int limit) {
		for (final E e : elements) {
			if (getter.get(e) > limit)
				return false;
		}
		return true;
	}

	static boolean isWidthSumWithinLimit(final Iterable<Element> elements,
			final int limit) {
		return isSumWithinLimit(elements, Element.WIDTH, limit);
	}

	static boolean isEachWidthWithinLimit(final Iterable<Element> elements,
			final int limit) {
		return isEachWithinLimit(elements, Element.WIDTH, limit);
	}

	static boolean isHeightSumWithinLimit(final Iterable<Element> elements,
			final int limit) {
		return isSumWithinLimit(elements, Element.HEIGHT, limit);
	}

	static boolean isEachHeightWithinLimit(final Iterable<Element> elements,
			final int limit) {
		return isEachWithinLimit(elements, Element.HEIGHT, limit);
	}

	static boolean isEachLengthWithinLimit(final Iterable<Thing> things,
			final int limit) {
		return isEachWithinLimit(things, Thing.LENGTH, limit);
	}
}

public class Example {

	public static void main(final String... args) {
		final Element e1 = new Element(2, 5);
		final Element e2 = new Element(4, 3);

		final List<Element> elements = new ArrayList<>();
		elements.add(e1);
		elements.add(e2);

		System.out.println(String.format("elements width sum check = %s",
				ConstraintChecker.isWidthSumWithinLimit(elements, 5)));
		System.out.println(String.format("elements each height check = %s",
				ConstraintChecker.isEachHeightWithinLimit(elements, 5)));

		final Thing t1 = new Thing(7);
		final Thing t2 = new Thing(1);

		final List<Thing> things = new ArrayList<>();
		things.add(t1);
		things.add(t2);

		System.out.println(String.format("things sum length check = %s",
				ConstraintChecker.isSumWithinLimit(things, Thing.LENGTH, 5)));
	}
}

Evidently, there are endless possibilities to using anonymous inner class constants. You can turn them into generic properties by giving them a generic type parameter on their return value; or make them modifiable by adding a set method; probably add some generic serialization, default handling, etc. – Have fun!