1

Coming from this answer I'm wondering how I can cast an object to <T extends Number & Comparable<T>>. I mean I have a method that is supposed to sort values. And in case the values are numbers I want to compare them with each other.

My naive first attempt was

  Object value1 = getAttributeValueFromHit(hit1, attributeName);
  Object value2 = getAttributeValueFromHit(hit2, attributeName);
  :
  :
  } else if (value1 instanceof Number) {
    Number nValue1 = (Number & Comparable<Number>) value1;
    /*
    Multiple markers at this line
      - Type safety: Unchecked cast from Object to Number & Comparable<Number>
      - Additional bounds are not allowed in cast operator at source levels below 1.8
    */
    Number nValue2 = (Number & Comparable<Number>) value2;
    /* same as above */
    return compareNumbers(nValue1, nValue2);
    /*
    Multiple markers at this line
      - Type safety: Unchecked cast from Object to Number & Comparable<Number>
      - Type safety: Unchecked cast from Object to Number & Comparable<Number>
      - Bound mismatch: The generic method compareNumbers(T, T) of type DataHitComparator is not applicable for the arguments (Number, Number). The inferred type Number is not a valid substitute for the bounded parameter <T extends Number & Comparable<T>>
      - Bound mismatch: The generic method compareNumbers(T, T) of type DataHitComparator is not applicable for the arguments (Number & Comparable<Number>, Number & Comparable<Number>). The inferred type Number & Comparable<Number> is not a valid substitute for the bounded parameter <T extends Number & Comparable<T>>
    */
  }

compareNumbers() is based on the linked answer:

private <T extends Number & Comparable<T>> int compareNumbers(T n1, T n2) {
  return n1.compareTo(n2);
}

Do I have any chance to make this work with Java 7?

Community
  • 1
  • 1
sjngm
  • 12,423
  • 14
  • 84
  • 114

1 Answers1

1

Use a generic type parameter (you can define one on your method or re-use one that is defined in the scope of the class).

public static <X extends Number & Comparable<X>> int test() {
    Object o1 = getAttributeValueFromHit(hit1, attributeName);
    Object o2 = getAttributeValueFromHit(hit2, attributeName);
    return compareNumbers((X) o1, (X) o2);
}

This will leave you with two warnings (because a cast to Comparable<X> cannot be checked) but it will not have any compile errors (and it works as well)


EDIT:
The above is absolutely true! To weave this into compareNumbers() and avoid the warnings it looks like this:

private <T extends Number & Comparable<T>> int compareNumbers(Number number1, Number number2) {
  @SuppressWarnings("unchecked")
  T number1Cast = (T) number1;
  @SuppressWarnings("unchecked")
  T number2Cast = (T) number2;
  return number1Cast.compareTo(number2Cast);
}

and its call:

    return compareNumbers((Number) value1, (Number) value2);
sjngm
  • 12,423
  • 14
  • 84
  • 114
Erwin Bolwidt
  • 30,799
  • 15
  • 56
  • 79
  • Whoa, nice :) I hope you don't mind that I added a version of `compareNumbers()` to your answer. – sjngm Jul 28 '14 at 08:25