问题是如果通用签名由几个类型相同的?
组成,则以下代码无法编译。
import java.util.Map;
import java.util.HashMap;
import java.util.function.Function;
public class Test {
private static <T> T findSelfReference(Map<T, T> map) {
for (Map.Entry<T, T> entry : map.entrySet()) {
if (entry.getKey() == entry.getValue()) {
return entry.getKey();
}
}
return null;
}
private static <T> T findSelfReference2(Map<T, T> map) {
for (T key : map.keySet()) {
if (map.get(key) == key) {
return key;
}
}
return null;
}
// Question: How to write the method signature that can ensure compile-time type safety? Both the signatures fail to compile.
// private static <T> String fun(Function<Map<T, T>, T> finder) {
private static String fun(Function<Map<?, ?>, ?> finder) {
Map<Integer, Integer> map1 = new HashMap<>();
// some processing to map1
Integer n = finder.apply(map1); // usage here, compile-time type checking wanted
Map<String, String> map2 = new HashMap<>();
// other processing to map2 depending on n
return finder.apply(finder, map2); // another usage
}
public static void main(String[] args) {
// Please don't change into helper class...
System.out.println(fun(Test::findSelfReference));
System.out.println(fun(Test::findSelfReference2));
}
}
在fun
中,在对finder.apply()
的每次调用中,类型T
都已修复。但在不同的电话中他们使用不同的类型。我尝试了通配符捕获(参考:here),但没有运气。
我不想将结果强制转换为必须在运行时进行检查的Object。所有类型检查都应在编译时完成。
是否可以不制作O(n)辅助类,其中n是内联函数的数量?
答案 0 :(得分:4)
问题是您希望finder
的{{1}}方法是通用的。
解决方案是使用通用方法定义您自己的功能接口。
apply
如果这被视为“助手类”,那么我不知道该告诉你什么。你正试图将一个方形钉子钉在圆孔上。 @FunctionalInterface
interface Finder {
<T> T apply(Map<T, T> map);
}
private static String fun(Finder finder) {
// same body
}
不是通用方法,因此您无法使用Function#apply
执行此操作。
答案 1 :(得分:2)
您要使用方法fun
尝试实现什么目标?
您使用通配符或类型参数Function
传递T
,然后您想将其应用于两种不同的具体类型(Integer
和String
)。
这不起作用:
Map<Integer, Integer> map1 = new HashMap<>();
// ...
Integer n = finder.apply(map1);
因为您希望finder
采用类型Integer
,但您在fun
声明中指定了类型未知(如果您使用{{ 1}})或某些无界类型?
(如果使用类型参数T
声明它)。但是,如果您要将其应用于T
,那么对于某些无界类型Integer
,您需要Function<Map<Integer, Integer>>
,而不是Function<Map<?, ?>, ?>
或Function<Map<T, T>, T>
。
你可以这样写 - 但方法T
本身或多或少没用。
fun
答案 2 :(得分:2)
你可以这样做:
private static <T> T fun(Function<Map<T, T>, T> finder, Map<T, T> map) {
return finder.apply(map);
}
private static Map<String, String> getStringMap(Integer n) {
String a = String.valueOf(n + 1);
Map<String, String> map2 = new HashMap<>();
map2.put("1", "2");
map2.put("3", "4");
map2.put("5", "7");
map2.put("3", a);
return map2;
}
private static Map<Integer, Integer> getIntMap() {
Map<Integer, Integer> map1 = new HashMap<>();
map1.put(1, 2);
map1.put(3, 4);
map1.put(5, 7);
map1.put(2, 2);
map1.put(8, 8);
return map1;
}
public static void main(String[] args) {
fun(Test::findSelfReference, getIntMap());
fun(Test::findSelfReference, getStringMap(1));
}
当你总能做到这一点时,我没有看到fun
方法的目的:
Function<Map<Integer, Integer>, Integer> m = Test::findSelfReference;
m.apply(getIntMap());