Skip to content

Number types

ljacqu edited this page Aug 20, 2023 · 1 revision

Given two Number types (e.g., long and float), can any number of the former type be converted to the latter type without loss of magnitude? The NumberType interface and the StandardNumberType enum implementation answers such questions and allows to perform conversions in different flavors.

Converting to other number type

StandardNumberType is an enum representing all basic Number implementations of the JDK: byte, short, int, long, float, double, BigInteger, and BigDecimal.

You can convert a number to a target type in different flavors:

// Convert unsafe: this is like casting directly in Java, with the potential of underflow and overflow,
// as seen in the second example. short s = (short) 100_000 = -31072
StandardNumberType.TYPE_SHORT.convertUnsafe(30);      // (short) 30
StandardNumberType.TYPE_SHORT.convertUnsafe(100_000); // (short) -31072

// Convert only if the value can be represented
StandardNumberType.TYPE_SHORT.convertIfNoLossOfMagnitude(30);      // Optional[(short) 30]
StandardNumberType.TYPE_SHORT.convertIfNoLossOfMagnitude(100_000); // Optional.empty

// Convert as close as possible: if the value is smaller or larger than what the type can represent,
// the min resp. max value is used
StandardNumberType.TYPE_SHORT.convertToBounds(30);      // (short) 30
StandardNumberType.TYPE_SHORT.convertToBounds(100_000); // (short) 32767 = Short.MAX_VALUE

Comparing number types

Every NumberType implementation (like the entries in StandardNumberType) define the range of values they can represent. Based on that, number types can be compared to each other:

StandardNumberType.TYPE_SHORT.supportsAllValuesOf(StandardNumberType.TYPE_BYTE);    // true
StandardNumberType.TYPE_SHORT.supportsAllValuesOf(StandardNumberType.TYPE_INTEGER); // false

StandardNumberType.TYPE_SHORT.compareToValueRange(30);      // WITHIN_RANGE
StandardNumberType.TYPE_SHORT.compareToValueRange(100_000); // ABOVE_MAXIMUM

Unwrap number

The JDK provides more Number implementations than the ones discussed so far: types like AtomicInteger and LongAdder can be "unwrapped" to one of the standard number types. Furthermore, Character, despite not implementing Number, has some interoperability with numbers in that its primitive type char can be cast to number types (even with implicit casts):

char c = 'A';
int i = c; // implicit cast to 65

Such values can be unwrapped with NumberTypes#unwrapToStandardNumberType:

char c = 'A';
NumberTypes.unwrapToStandardNumberType(c); // Integer(65)

LongAdder longAdder = new LongAdder();
longAdder.add(1234);
NumberTypes.unwrapToStandardNumberType(longAdder); // Long(1234L)

AtomicInteger atomicInteger = new AtomicInteger(30);
NumberTypes.unwrapToStandardNumberType(atomicInteger); // Integer(30)

Home

Documentation

  1. Array utils
  2. ClassUtils
  3. Number types

Internal (for development)

  1. Performing a release
  2. Terminology
Clone this wiki locally