Common generic method to handle operations on subclasses of java.lang.Number

Viewed 78

I have a class MyGen which takes two generic arguments and has a method getValue()

public interface MyGen<E,T> {

    T getValue();
}

Usually the second generic type would be either Long or Integer.

Then, I wrote a method to combine the objects when the second generic type is Long as below:

public static <E extends MyGen<?, Long>> long combineValue(Set<E> set) {
    return set.stream()
              .map(MyGen::getValue)
              .reduce(0L, (a,b) -> a | b);
}

Now I want to have a similar method when the second type is an Integer. So I tried updating the above same method to :

public static <E extends MyGen<?, ? extends Number>> long combineValue(Set<E> set) {
    return (long) set.stream()
                     .map(MyGen::getValue)
                     .reduce((a,b) -> a | b) // error1
                     .orElse(0); // error2

}

But the following errors are displayed:

  1. error1

The operator | is undefined for the argument type(s) capture#4-of ? extends java.lang.Number, capture#4-of ? extends java.lang.Number

  1. error2

The method orElse(capture#4-of ? extends Number) in the type Optional<capture#4-of ? extends Number> is not applicable for the arguments (int)

Is there any way to handle both Long and Integer in the same method or could it be done only using two separate methods?

1 Answers

You seem to be fine about the return value of this common method being long. In that case, it is possible, because you can get a long from a Number using longValue:

public static long combineValue(Set<? extends MyGen<?, ? extends Number>> set) {
    return set.stream()
              .map(MyGen::getValue)
              .mapToLong(Number::longValue)
              .reduce(0L, (a,b) -> a | b);
}

You basically turn every number into longs first, and then do the reduction.

Related