How to overload a Function with generic parameter in Java 8?
public class Test<T> {
List<T> list = new ArrayList<>();
public int sum(Function<T, Integer> function) {
return list.stream().map(function).reduce(Integer::sum).get();
}
public double sum(Function<T, Double> function) {
return list.stream().map(function).reduce(Double::sum).get();
}
}
Error: java: name clash: sum(java.util.function.Function<T,java.lang.Double>) and sum(java.util.function.Function<T,java.lang.Integer>) have the same erasure
The example you present in your question has got nothing to do with Java 8 and everything to do with how generics work in Java.
Function<T, Integer> functionandFunction<T, Double> functionwill go through type-erasure when compiled and will be transformed toFunction. The rule of thumb for method overloading is to have different number, type or sequence of parameters. Since both your methods will transform to take aFunctionargument, the compiler complains about it.That being said, srborlongan has already provided one way to resolve the issue. The problem with that solution is that you have to keep modifying your
Testclass for each and every type of operation (addition,subtraction,etc) on different types (Integer,Double, etc). An alternate solution would be to usemethod overridinginstead ofmethod overloading:Change the
Testclass a bit as follows :Create a subclass of
Testthat will add twoIntegers.Client code can then use the above code as follows :
The advantage of using this approach is that your
Testclass is in line with theopen-closedprinciple. To add a new operation such as multiplication, all you have to do is add a new subclass ofTestandoverridetheoperationmethod to multiply two numbers. Club this with the Decorator pattern and you can even minimize the number of sub-classes that you have to create.Note The example in this answer is indicative. There are a lot of areas of improvement (such as make
Testa functional interface instead of an abstract class) which are beyond the scope of the question.