NumberHelper { public static Number add(final Number a, final Number b) { final Class<? extends Number> clazz = getHighestCommonNumberClass(a, b); return getHelper(clazz).add.apply(a, b); } private  NumberHelper(final BiFunction<Number, Number, Number> add,
                         final BiFunction<Number, Number, Number> sub,
                         final BiFunction<Number, Number, Number> mul,
                         final BiFunction<Number, Number, Number> div,
                         final BiFunction<Number, Number, Number> min,
                         final BiFunction<Number, Number, Number> max,
                         final BiFunction<Number, Number, Integer> cmp
    ); static Class<? extends Number> getHighestCommonNumberClass(final Number... numbers); static Class<? extends Number> getHighestCommonNumberClass(final boolean forceFloatingPoint, final Number... numbers); static Number add(final Number a, final Number b); static Number sub(final Number a, final Number b); static Number mul(final Number a, final Number b); static Number div(final Number a, final Number b); static Number div(final Number a, final Number b, final boolean forceFloatingPoint); static Number min(final Number a, final Number b); static Comparable min(final Comparable a, final Comparable b); static Number max(final Number a, final Number b); static Comparable max(final Comparable a, final Comparable b); static Integer compare(final Number a, final Number b); final BiFunction<Number, Number, Number> add; final BiFunction<Number, Number, Number> sub; final BiFunction<Number, Number, Number> mul; final BiFunction<Number, Number, Number> div; final BiFunction<Number, Number, Number> min; final BiFunction<Number, Number, Number> max; final BiFunction<Number, Number, Integer> cmp; }
@Test public void shouldAddAndReturnCorrectType() { assertEquals(2, add((byte) 1, (byte) 1)); assertEquals(2, add((byte) 1, (short) 1)); assertEquals(2, add((byte) 1, 1)); assertEquals(2L, add((byte) 1, 1L)); assertEquals(2F, add((byte) 1, 1F)); assertEquals(2D, add((byte) 1, 1D)); assertEquals(BigInteger.ONE.add(BigInteger.ONE), add((byte) 1, BigInteger.ONE)); assertEquals(BigDecimal.ONE.add(BigDecimal.ONE), add((byte) 1, BigDecimal.ONE)); assertEquals(2, add((short) 1, (short) 1)); assertEquals(2, add((short) 1, 1)); assertEquals(2L, add((short) 1, 1L)); assertEquals(2F, add((short) 1, 1F)); assertEquals(2D, add((short) 1, 1D)); assertEquals(BigInteger.ONE.add(BigInteger.ONE), add((short) 1, BigInteger.ONE)); assertEquals(BigDecimal.ONE.add(BigDecimal.ONE), add((short) 1, BigDecimal.ONE)); assertEquals(2, add(1, 1)); assertEquals(2L, add(1, 1L)); assertEquals(2F, add(1, 1F)); assertEquals(2D, add(1, 1D)); assertEquals(BigInteger.ONE.add(BigInteger.ONE), add(1, BigInteger.ONE)); assertEquals(BigDecimal.ONE.add(BigDecimal.ONE), add(1, BigDecimal.ONE)); assertEquals(2L, add(1L, 1L)); assertEquals(2D, add(1L, 1F)); assertEquals(2D, add(1L, 1D)); assertEquals(BigInteger.ONE.add(BigInteger.ONE), add(1L, BigInteger.ONE)); assertEquals(BigDecimal.ONE.add(BigDecimal.ONE), add(1L, BigDecimal.ONE)); assertEquals(2F, add(1F, 1F)); assertEquals(2D, add(1F, 1D)); assertEquals(BigDecimal.ONE.add(BigDecimal.ONE).setScale(1, RoundingMode.HALF_UP), add(1F, BigInteger.ONE)); assertEquals(BigDecimal.ONE.add(BigDecimal.ONE).setScale(1, RoundingMode.HALF_UP), add(1F, BigDecimal.ONE)); assertEquals(2D, add(1D, 1D)); assertEquals(BigDecimal.ONE.add(BigDecimal.ONE).setScale(1, RoundingMode.HALF_UP), add(1D, BigInteger.ONE)); assertEquals(BigDecimal.ONE.add(BigDecimal.ONE).setScale(1, RoundingMode.HALF_UP), add(1D, BigDecimal.ONE)); assertEquals(BigInteger.ONE.add(BigInteger.ONE), add(BigInteger.ONE, BigInteger.ONE)); assertEquals(BigDecimal.ONE.add(BigDecimal.ONE), add(BigInteger.ONE, BigDecimal.ONE)); assertEquals(BigDecimal.ONE.add(BigDecimal.ONE), add(BigDecimal.ONE, BigDecimal.ONE)); }