1

Although I use here Hamcrest library, it is probably not an Hamcrest issue but pure Java...

I have the following method:

public static void isGreaterThan(int valueToValidate, int minExpectedVal) {
    MatcherAssert.assertThat(valueToValidate, greaterThan(minExpectedVal));
}

I'd like to generalize it to something like:

public static <T> void isGreaterThan(T valueToValidate, T minExpectedVal) {
    MatcherAssert.assertThat(valueToValidate, greaterThan(minExpectedVal));
}

or

public static void isGreaterThan(Number valueToValidate, Number minExpectedVal) {
    MatcherAssert.assertThat(valueToValidate, greaterThan(minExpectedVal));
}

Hamcrest greaterThan signature is:

<T extends Comparable<T>> Matcher<T> greaterThan(T value)

and assertThat signature:

<T> void assertThat(T actual, Matcher<? super T> matcher)

However, on both cases, I get an error on minExpectedVal saying that it cannot be applied as T.

How can I overcome this?

2
  • 1
    As per hamcrest signature your Typed parameter should inherit comparable interface. As per docs Number class is not inheriting from Comparable interface Commented Aug 7, 2019 at 14:03
  • 1
    @dushkin You have a misconception about what java.lang.Number represents. It is not a generic number type, as the name would suggest. The name is misleading, as it only represents an object that can be converted to any of the primitive numeric types. That conversion is not lossless and that is the reason why it does not implement Comparable. And that is why it really cannot be used to represent a number as one would expect. Commented Nov 3, 2021 at 5:46

1 Answer 1

3

You need to add a bound to your generic version.

public static <T extends Comparable<T>> void isGreaterThan(T valueToValidate, T minExpectedVal) {
    MatcherAssert.assertThat(valueToValidate, greaterThan(minExpectedVal));
}

Note that Numbers are not comparable; for them you could do

public static void isGreaterThan(Number valueToValidate, Number minExpectedVal) {
    MatcherAssert.assertThat(valueToValidate.doubleValue(), greaterThan(minExpectedVal.doubleValue()));
}

EDIT: Torben is correct that doubleValue() is not necessarily lossless. However, the only standard Number subtypes for which it isn't are Long, BigInteger and BigDecimal, so you could check for them explicitly. But the generic version is better either way.

Sign up to request clarification or add additional context in comments.

2 Comments

Please see my comment in the original question. Number is not meant to be used like this. The conversion to double will lose information so the comparison it is not accurate and should not be relied upon.
@Torben Good point, see the edit.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.