*bodies*. Happily, this major oversight has been fixed in Java 1.8.

But now I want to rail against another aspect of interfaces and abstract types (or rather their usage) that I think is by far the worst thing that the Java designers ever messed up. The "Number" type.

First, let's look at three simple reasons why

*java.lang.Number*is so bad.

- it should be an interface -- or rather several interfaces -- but instead it is an abstract type;
- if it is going to be an abstract type, then at least let's have it implement
*Comparable<Number>*--- but it doesn't; all of its sub-classes, say*X*, implement Comparable<X> but that's not the same thing at all: if you need a generic type that implements Number*and*Comparable, it can't be done without creating your own type! - it doesn't even have a method to let you find out if the type is integral or real (forget about complex) -- you have a Number, you can check if it implements Integer, Long, etc. but if somebody creates a new sub-class of Number that happens to be integral, you won't catch it.

Let's think about how we would go about defining an interface (or interfaces) to represent numbers. Sounds pretty straightforward, right? But it isn't quite that simple. There's a world of difference between the integers, where the

*successor*or

*predecessor*operators make perfect sense, and the

*real*numbers where those operators don't make much sense -- while operators such as

*round*are useful. And then there are complex numbers, rational numbers, irrational numbers, etc. etc. In other words, different types of numbers require different methods. In fact, to put it another way by inverting the question, the operators essentially

*define*the number classes. Is there a fundamental set of operators that would apply to all numbers? There really isn't. But a reasonable set that works with most types of number is this: addition, multiplication, negation, perhaps some others, including

*compare with*.

But already we run into problems. If the set of numbers you're modeling is the positive integers, then negation makes no sense.

So, let's start out with something like this:

public interface Numeric extends Comparable<numeric> { Numeric add(Numeric other); Numeric multiply(Numeric other); }

public interface Integral extends Numeric { Numeric negate(Numeric other); }

So far so good. We can now define an IntegralBase class based on the int primitive:

public class IntegralBase implements Integral { private int value; public IntegralBase(int value) { super(); this.value = value; } @Override public Numeric add(Numeric other) { if (other instanceof IntegralBase) return new IntegralBase(this.value+((IntegralBase) other).value); throw new RuntimeException("cannot add non-IntegralBase object"); } @Override public Numeric multiply(Numeric other) { if (other instanceof IntegralBase) return new IntegralBase(this.value*((IntegralBase) other).value); throw new RuntimeException("cannot multiply non-IntegralBase object"); } @Override public int compareTo(Numeric other) { if (other instanceof IntegralBase) return Integer.compare(this.value, ((IntegralBase) other).value); throw new RuntimeException("cannot add non-IntegralBase object"); } @Override public Integral negate(Integral other) { return new IntegralBase(-this.value); } }

*Integral*(or, more specifically, an

*IntegralBase*). What if the "int" primitive isn't sufficient for our purposes and we need a

*BigInteger*? We could define a

*BigIntegral*class just like the one above. Or we could make

*Integral*generic, except of course that "int" cannot be a generic type because it's a primitive.

But even this is better than the setup that the Java designers gave us. What we have in Java is an abstract type (not an interface) called

*Number*.public abstract class Number implements java.io.Serializable { public abstract int intValue(); public abstract double doubleValue(); // etc. etc. }

The designers of the

*math3*package from Apache "commons" have helped somewhat. They do bring in a little mathematics withe the*Field*and*FieldElement*interfaces. And they provide a type for rational numbers in*BigFraction*.
But in my humble opinion, Java, while it is admittedly a general-purpose language, could have done so much better right from the start.

OK, back to work.