AggregationUtils implements Serializable { @SuppressWarnings("unchecked") public static <T extends Comparable, I extends Comparable> int compare(T o1, I o2){ if(o1.getClass() == o2.getClass()){ return o1.compareTo(o2); }else if(Number.class.isAssignableFrom(o1.getClass()) && Number.class.isAssignableFrom(o2.getClass())) { return Double.compare(((Number) o1).doubleValue(), ((Number) o2).doubleValue()); }else if(String.class.isAssignableFrom(o1.getClass()) || String.class.isAssignableFrom(o2.getClass())){ return o1.toString().compareTo(o2.toString()); }else{ throw new UnsupportedOperationException( String.format("Could not compare %s with %s!",o1.getClass(),o2.getClass()) ); } } private  AggregationUtils(); @SuppressWarnings("unchecked") // both types are the same and extends from Comparable static int compare(T o1, I o2); @SuppressWarnings("unchecked") // manually checked type security static Double add(T o1, I o2); @SuppressWarnings("unchecked") // manually checked type security static Double subtract(T o1, I o2); @SuppressWarnings("unchecked") // manually checked type security static Double multiply(T m1, I m2); @SuppressWarnings("unchecked") // manually checked type security static Double divide(T divided, I divider);  }
@Test public void compare() { Instant now = Instant.now(); assertEquals(0, AggregationUtils.compare(1, 1)); assertEquals(0, AggregationUtils.compare(1L, 1L)); assertEquals(0, AggregationUtils.compare(1F, 1F)); assertEquals(0, AggregationUtils.compare(1D, 1D)); assertEquals(0, AggregationUtils.compare("1", "1")); assertEquals(0, AggregationUtils.compare(Date.from(now), Date.from(now))); assertEquals(0, AggregationUtils.compare(now, now)); assertEquals(0, AggregationUtils.compare(now, now.toString())); assertEquals(0, AggregationUtils.compare(1, "1")); assertEquals(0, AggregationUtils.compare(1D, 1L)); }