Да, вы можете реализовать такой метод, так как оба Integer
и Long
продлить Number
. Например, вы можете использовать wildcard type для типа элемента списка:
public static long total(List<? extends Number> list) {
long sum = 0;
for (Number n : list) {
if (!(n instanceof Byte || n instanceof Short || n instanceof Integer || n instanceof Long)) {
throw new IllegalArgumentException();
}
sum += n.longValue();
}
return sum;
}
это работает только для целочисленных типов однако, так как sum
переменных и возвращаемое значение имеют типа long
.
В идеале вы хотели бы иметь возможность использовать метод с Float
с и Double
с и возвращает объект того же типа, что и тип элемента списка, но это не так легко сделать по двум причинам:
- Единственное, что вы можете сделать с помощью
Number
, это получить его значение как один из примитивных типов номеров. Вы не можете суммировать два из них в зависимости от числа.
- Невозможно создать 0-объект правого класса.
EDIT:Намного позже ...
Просто для удовольствия, позволяет сделать это хороший способ для Java. Дело в том, что вы должны вручную предоставить две операции, упомянутые выше. Вид стоимости с двумя такими операциями обычно называют monoid в контексте алгебры и функционального программирования.
Проблема может быть решена путем создания объектов, которые представляют моноидных операции:
interface MonoidOps<T> {
T id();
T op(T o1, T o2);
}
Метод total
теперь может быть реализован, чтобы принять объект этого типа в дополнение к списку:
public static <T> T total(List<T> list, MonoidOps<T> ops) {
T sum = ops.id();
for (T e : list) {
sum = ops.op(e, sum);
}
return sum;
}
Чтобы предоставить MonoidOps
реализации для числовых классов, создайте простой вспомогательный класс:
class SimpleMonoidOps<T> implements MonoidOps<T> {
private final T idElem;
private final BinaryOperator<T> operation;
public SimpleMonoidOps(T idElem, BinaryOperator<T> operation) {
this.idElem = idElem;
this.operation = operation;
}
public T id() {
return idElem;
}
public T op(T o1, T o2) {
return operation.apply(o1, o2);
}
}
В MonoidOps
реализации теперь могут быть написаны аккуратно, как это:
static final MonoidOps<Integer> INT_MONOID_OPS = new SimpleMonoidOps<>(0, Integer::sum);
static final MonoidOps<Double> DOUBLE_MONOID_OPS = new SimpleMonoidOps<>(0.0, Double::sum);
И метод total
будет называться так:
int sum = total(Arrays.asList(1, 2, 3), INT_MONOID_OPS);
Узнавайте что-то новое каждый день :) Спасибо! – Ivan