I'm doing something wrong but not sure what. Trying to make a lookup map that provides me functions I can call on.
Simple demonstration of the problem:
aa.java
public class aa { /** doesn't matter for this example */}
ab.java
public class ab extends aa { /** doesn't matter for this example */}
Helper.java
public static short[] convert(ab foo)
{
//doesn't matter but eventually returns a short[] i.e.
return new short[5];
}
private interface aaConverterI
{
public <T extends aa> short[] method(Function<T, short[]> in);
}
private static Map<String, aaConverterI> bar = new HashMap<>();
static
{
bar.put("blah", Helper::convert);
}
Compiler says The type Helper does not define convert(Function<T, short[]>) that is applicable here on the Helper::convert, The method put(String, Helper.aaConverterI) in the type Map<String, aaConverterI> is not applicable for the arguments (String, Helper::convert).
If I add a
static Function<ab, short[]> blahFunction = Helper::convert;
There is no complaints about that, and I can change the put to
bar.put("blah", blahFunction);
Which then makes the compiler just complain on the put that The method put(String, Helper.aaConverterI) in the type Map<String, Helper.aaConverterI> is not applicable for the arguments (String, Function<ab, short[]>).
I'm missing something but I'm not sure what. Tried adding a @FunctionalInterface to convert declaration and that didn't change anything.
What am I missing? Thank you!
This interface:
... satisfies the requirements for use as a functional interface. For a method reference to be compatible with this functional interface, its signature must match that of
aaConverterI.method(). That is, it accepts a matchingFunctionas its argument and returns ashort[].This:
... does not have such a signature. It accepts an argument of type
ab, which is not aFunction, all other considerations notwithstanding. That explains your error.I suspect you meant to define
aaConverterImore like this:... but even that does not work.
aaConverterI.method()can accept an argument of typeaaor any of its subtypes, butHelper.convert()cannot accept an argument of typeaa(for example). Note too thataaConverter.method()is not actually getting anything useful out of its type parameterization. You might as well just perform the erasure manually if that's what you really wanted.Another, more likely alternative would involve making the interface generic instead of the method:
... then you could write:
, but that probably still doesn't help you, because you will find that there is no typesafe way to use any of the methods you pull back out of that map.
Bottom line:
Java generics are not powerful enough to parameterize the
Mapyou would really like to define, where the keys are (say)Class<?>and the values are typeaaConverterI<the-type-corresponding-to-the-key>. Your best bet probably is, in fact, the manual erasure:, where you write all your converter methods with that exact signature and, yes, cast or
Class.cast()within.