-
Notifications
You must be signed in to change notification settings - Fork 0
Number types
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.
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
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
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)
Documentation
Internal (for development)