Is it possible to compare against zero value in a generic method extending Number?

StackOverflow https://stackoverflow.com/questions/20915466

  •  24-09-2022
  •  | 
  •  

سؤال

I currently have a method to return the non-zero indices in an iterable. I want this method to be able to handle any class extending java.lang.Number. Number, of course, does not implement Comparable. But I don't want to have separate methods for Long, Integer, etc. As of now, this is what I have:

public static <T extends Number & Comparable<? super T>> nonZeroIndices(Iterable<T> iterable) {
    Set<Integer> nonzero_indices = Sets.newTreeSet();
    Iterator<T> iterator = iterable.iterator();
    int i = 0;
    while (iterator.hasNext()) {
        T t = iterator.next();
        if (t.doubleValue() != 0) // This is what is bothering me
            nonzero_indices.add(i);
        i++;
    }
    return nonzero_indices;
}

But I want to avoid doubleValue(). I would also like to avoid having a bunch instanceOf calls in my method. Can I make this method to work on type T where T extends Number and T implements Comparable?

EDIT Using <T extends Number & Comparable<? super T>> (as suggested by Sotirios) will still require a bunch of instanceOf statements, which I want to avoid. I was hoping that I can safely cast zero to type T, but the compiler issues a warning saying "unchecked cast".

To be more specific, I tried

if (t.compareTo((T) new Integer(0) == 0)

but it issues the warning.

هل كانت مفيدة؟

المحلول

The problem is that Integer is specifically Comparable<Integer>, Double is specifically Comparable<Double>, and so on, so to use their compareTo, you have to pass in a reference of the appropriate type, which means that you have to have an object of the appropriate type. Note that the cast in (Double) new Integer(0) will never succeed, because you can't have a reference of one type that points to an object of an incompatible type. (And actually it's a compile error, because the compiler can tell in this case that the cast will never succeed.)

I think your doubleValue approach is probably the best one.

نصائح أخرى

It is not possible with the Number hierarchy. You have to use instanceof.

In general, your doubleValue trick seems to work most of the time. I could construct a false positive with BigDecimal:

new BigDecimal("0.000..<repeats 380 times>..001").doubleValue() == 0

If that is a problem for you, you might want to add a special case for BigDecimal.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top