code: @SuppressWarnings({ "unchecked", "rawtypes" })
      public static int compare(Number left, Number right) {
          
          // compare directly when both are the same type and implement 
          // comparable (ie: Integer, Long, Short, etc wrappers all do)
          if (left.getClass().isAssignableFrom(right.getClass()) &&
              Comparable.class.isAssignableFrom(left.getClass())) {
              
              return ((Comparable) left).compareTo(right);
          }
  
          // compare directly in opposite direction in case the right side is
          // higher in the hiearchy
          else if (right.getClass().isAssignableFrom(left.getClass()) &&
                   Comparable.class.isAssignableFrom(right.getClass())) {
              return -((Comparable) right).compareTo(left);
          }
          
          // when not the same type, attempt to coerce to the greatest matching
          // types
          
          int type = getCompatibleType(left, right);
          if (type == TYPE_DOUBLE) {
              return compare(left.doubleValue(), right.doubleValue());
          }
          else if (type == TYPE_FLOAT) {
              return compare(left.floatValue(), right.floatValue());
          }
          else if (type == TYPE_LONG) {
              return compare(left.longValue(), right.longValue());
          }
          else if (type == TYPE_INT) {
              return compare(left.intValue(), right.intValue());
          }
          else {
              throw new IllegalStateException("unsupported number type: " + type);
          }
      }
docs: This performs a mostly safe comparison between two abstract numbers.
  If both numbers share the same hiearchy and that hiearchy implements
  {@link Comparable}, then {@link Comparable#compareTo(Object)} is used to
  compare the values.  Otherwise, the most compatible data type is used
  to perform the conversion.  For example, a {@link Integer} compared to
  a {@link Long} would compare as a long via {@link Number#longValue()}.
  If either data type cannot be determined, then they are assumed to be
  doubles and compared in order to avoid potential data loss.
  
  @param left The left value to compare
  @param right The right value to compare
  
  @return less than 0 if left is less than right, 0 if equal, and greater
  than 0 if left is greater than right