4

I have some code with 3 overriding methods that perform the same operation ( code is identically for each method) on the Inputs, the only difference between them is the input parameter type

private List<String> extractDoubleValues(Function<MyClass, List<Double>> extractions)
private List<String> extractLongValues(Function<MyClass List<Long>> extractions)
private List<String> extractIntegerValues(Function<MyClass, List<Integer>> extractions)

I was trying to attempt to replace these 3 methods with a single method that makes us of generic wildcards as follows

private List<String> extractNumberValues(Function<MyClass, List<? extends Number>> extractions)

When I attempt to use the above generic method in place of one of the 3 type specific methods

Function<MyClass, List<Integer>> intExtractions; 
List<String> extractedValues = extractNumberValues(intExtractions);

I get a the following compilation error on the second line of code above

Error:(59, 80) java: incompatible types: java.util.function.Function<MyClass,java.util.List<java.lang.Double>> cannot be converted to java.util.function.Function<MyClass,java.util.List<? extends java.lang.Number>>

I've successfully replaced duplicate methods with the wildcard before, as bellow

List<String> convertNumberListToStringList(List<Integer> numberList)
List<String> convertNumberListToStringList(List<Double> numberList)

with

List<String> convertNumberListToStringList(List<? extends Number> numberList)

I'm new to the idea of generics so I was curious as why the above would fail to compile? I do not quite understand why it would fail to compile

user3242143
  • 43
  • 1
  • 3
  • 4
    Technically a dupe of: https://stackoverflow.com/questions/2745265 . You need `Function>`. P.s. Maybe this one is a better dupe: https://stackoverflow.com/questions/22806202 – Jorn Vernee Dec 07 '17 at 11:10

2 Answers2

1

When you declare the instance of Function<MyClass, List<Number>> as Function<MyClass, List<Integer>> you restrict other types of number to be added to the List, i.e. Long and Double can't be added to the List<Integer>. Hence the incompatible type error.

Pradeep Pati
  • 5,779
  • 3
  • 29
  • 43
1

Major problem(or i should say feature?) here is generic are used only during compilation. During runtime you do not have any information about generic. In other words you have to consider List<Integer> and List<Double> and completelly different types. If you see inside Fucntion class you will see <T, R> without wildcard. So even Function use List<Integer> and List<Double> as completelly different types. If y ou want to say to Function that R will be something of List type, you have to code it like:

Function<SomeClass, ? extends List<? extends SomeOtherClass>>

By code above you are telling that R will be List for sure and list will contain instances of SomeOtherClass.

Main point during work with generic is that generic changes original class to some other class...

Majlanky
  • 198
  • 2
  • 9
  • Thank you for the reply, I believe I understand them better now, So basically when using wildcard generics in nested classes, the generic type has to be bubbled up to the top level class because that's the class being checked by the compliler first and not each individual nested class – user3242143 Dec 07 '17 at 15:07
  • You should read some articles about generics to get deeper knowledge instead simplified lookups like i gave you but yes, you can use this rule at begin to avoid some confusing situations... – Majlanky Dec 08 '17 at 09:21