Java: Generic methods and numbers
There are ways you can hack this together but in all honestly, generics is simply not the way to go here. Build a method for each concrete primitive wrapper type and implement them separately. It'll be way too much of a headache to make it generic; arithmetic operations can't happen generically.
You don't really gain anything by making it generic, either. It's such simple and constant code that you aren't worried about code duplication, since it's not going to change. And people aren't going to be passing in their own type of Number to your code; the domain of types it applies to is already well defined and finite.
I've done that recently (based on lambdaj code) beware it will need all your elements to be the same type (you can't really add a Byte
and a BigDecimal
) and can throw a CCE if it isn't the case and won't handle custom Number
:
public class SumAggregator<T extends Number> {
public T aggregate(Iterable<T> iterable) {
T result = null;
for (T item : iterable) {
result = aggregate(result, item);
}
return result;
}
@SuppressWarnings("unchecked")
protected T aggregate(T first, T second) {
if (first == null) {
return second;
} else if (second == null) {
return first;
} else if (first instanceof BigDecimal) {
return (T) aggregate((BigDecimal) first, (BigDecimal) second);
} else if (second instanceof BigInteger) {
return (T) aggregate((BigInteger) first, (BigInteger) second);
} else if (first instanceof Byte) {
return (T) aggregate((Byte) first, (Byte) second);
} else if (first instanceof Double) {
return (T) aggregate((Double) first, (Double) second);
} else if (first instanceof Float) {
return (T) aggregate((Float) first, (Float) second);
} else if (first instanceof Integer) {
return (T) aggregate((Integer) first, (Integer) second);
} else if (first instanceof Long) {
return (T) aggregate((Long) first, (Long) second);
} else if (first instanceof Short) {
return (T) aggregate((Short) first, (Short) second);
} else {
throw new UnsupportedOperationException("SumAggregator only supports official subclasses of Number");
}
}
private BigDecimal aggregate(BigDecimal first, BigDecimal second) {
return first.add(second);
}
private BigInteger aggregate(BigInteger first, BigInteger second) {
return first.add(second);
}
private Byte aggregate(Byte first, Byte second) {
return (byte) (first + second);
}
private Double aggregate(Double first, Double second) {
return first + second;
}
private Float aggregate(Float first, Float second) {
return first + second;
}
private Integer aggregate(Integer first, Integer second) {
return first + second;
}
private Long aggregate(Long first, Long second) {
return first + second;
}
private Short aggregate(Short first, Short second) {
return (short) (first + second);
}
}
This code executed on ideone with examples.