我做错了什么,但不确定是什么。 尝试制作一个查找地图,为我提供可以调用的功能。
简单演示问题:
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);
}
编译器在 Helper::convert 上显示
The type Helper does not define convert(Function<T, short[]>) that is applicable here
,The method put(String, Helper.aaConverterI) in the type Map<String, aaConverterI> is not applicable for the arguments (String, Helper::convert)
。
如果我添加一个
static Function<ab, short[]> blahFunction = Helper::convert;
对此没有任何抱怨,我可以将 put 更改为
bar.put("blah", blahFunction);
这使得编译器只是抱怨
The method put(String, Helper.aaConverterI) in the type Map<String, Helper.aaConverterI> is not applicable for the arguments (String, Function<ab, short[]>)
。
我错过了一些东西,但我不确定是什么。尝试添加
@FunctionalInterface
来转换声明,但没有改变任何内容。
我错过了什么?谢谢!
此界面:
private interface aaConverterI
{
public <T extends aa> short[] method(Function<T, short[]> in);
}
...满足用作功能接口的要求。为了使方法引用与此功能接口兼容,其签名必须与
aaConverterI.method()
的签名匹配。也就是说,它接受匹配的 Function
作为其参数并返回 short[]
。
这个:
public static short[] convert(ab foo)
...没有有这样的签名。尽管考虑到所有其他因素,它接受
ab
类型的参数,但它不是 Function
。这解释了你的错误。
我怀疑你的意思是像这样定义
aaConverterI
:
private interface aaConverterI
{
public <T extends aa> short[] method(T in);
}
...但即使这样也行不通。
aaConverterI.method()
可以接受 aa
类型或其任何子类型的参数,但 Helper.convert()
不能接受 aa
类型的参数(例如)。还要注意,aaConverter.method()
实际上并没有从其类型参数化中获得任何有用的东西。如果您确实想要的话,也可以手动执行擦除。
另一种更可能的替代方案是使接口变得通用而不是方法:
private interface aaConverterI<T extends aa>
{
public short[] method(T in);
}
...那么你可以写:
private static Map<String, aaConverterI<? extends aa>> bar = new HashMap<>();
static
{
bar.put("blah", Helper::convert);
}
,但这可能 still 对你没有帮助,因为你会发现没有类型安全的方法来使用你从该映射中撤回的任何方法。
底线:
Java 泛型不够强大,无法参数化您真正想要定义的
Map
,其中键是(比如说)Class<?>
,值是类型 aaConverterI<the-type-corresponding-to-the-key>
。事实上,您最好的选择可能是手动擦除:
private interface aaConverterI
{
public short[] method(aa in);
}
,您可以在其中使用该确切的签名编写所有转换器方法,是的,在其中进行强制转换或
Class.cast()
。