在使用泛型、通配符和函数式编程尝试一段代码时,我有一个疑问,下面是一个简单的程序
import java.util.function.Function;
public static void main(String[] args) {
String x = "";
String y = getFormData().apply(x);
}
private static Function<?, String> getFormData() {
return x -> ((String) x).concat("asd");
}
上面的程序在线上抛出一个错误
String y = getFormData().apply(x);
Function
中的apply (capture<?>)
不能应用于 (java.lang.String
)
但是如果我将 getFormData() 函数更改为
private static Function<? super String, String> getFormData() {
return x -> ((String) x).concat("asd");
}
错误消失了。
有人可以解释为什么会发生这种情况吗?我知道<? super String>
意味着任何超类型的字符串或字符串本身。
方法的第一个版本:
Function<?, String> getFormData() {...}
可以返回Function<Integer, String>
.那么这个函数显然不能应用于String
!
但是,在第二种情况下:
Function<? super String, String> getFormData() {...}
不允许返回Function<Integer, String>
。
类型表达式Function<?, String>
与任何返回String
的Function
兼容,无论其参数类型如何。 例如,它与Function<Integer, String>
. 因此,如果您没有比这更具体的信息,那么您就无法安全地将String
或其他任何东西作为其apply
方法的参数传递。 类型表达式未提供足够的信息来确定允许的参数类型。
另一方面,类型表达式Function<? super String, String>
仅与接受String
或其超类型之一作为参数(并返回String
)的Function
兼容。 将此类函数应用于String
始终是安全的。 如果可以创建这样的子类,则将其应用于String
子类的实例也是安全的。 然而,将其应用于任何其他类型是不安全的,即使是严格的超类型String
,因为Function
的第一个类型参数总是可以String
本身。
总的来说,由于这意味着唯一可接受的参数类型是String
,使用通配符似乎只会带来混乱。 我只会改用Function<String, String>
。