Don’t use interfaces for values

If you’re defining an Java API, value objects are your friend. And interfaces aren’t suited to that task.

Java gets this wrong all over:

  • Annotations. They use interfaces to define value objects, and consequently it’s quite awkward for tools like Guice to define annotation values. is boilerplate hell.

  • Generic type descriptors. Hidden inside each of Guava, Gson, and Guice are mechanical implementations of GenericArrayType, ParameterizedType, TypeVariable, and WildcardType. This wasted code is particularly tragic because Java 8’s TypeVariable interface broke backwards compatibility.

  • Collections. The List and Set interfaces are too big to implement directly, so we have AbstractList and AbstractSet. If List and Set were just abstract classes, Java 8 wouldn’t have needed default methods!

I’m annoyed that this mistake continues to be made. JAX-RS defined its headers type as an interface without a good way to build an instance in a unit test. Instead every application needs its own implementation for testing.

Interfaces are wonderful! They’re useful in all kinds of modeling problems. But for defining value objects, interfaces are a bad fit.