java - Java静态多态(重载)和泛型之间的继承
问题描述
Java 11(可能无关紧要):
public static String toString(Object obj) {
return ReflectionToStringBuilder.toString(obj, ToStringStyle.SHORT_PREFIX_STYLE);
}
public static String toString(Collection<Object> collection) {
return collection.stream()
.map(SaLogUtils::toString)
.collect(Collectors.joining(", ", "[", "]"));
}
public static void main(String[] args) {
List<Integer> list = List.of(Integer.valueOf(1));
System.out.println(SaLogUtils.toString(list));
System.out.println(SaLogUtils.toString(List.of(Integer.valueOf(1))));
}
惊人的输出:
// from toString(Object)
ImmutableCollections.List12[e0=1,e1=<null>]
// from toString(Collection<Object>)
[Integer[value=1]]
为什么Java静态选择不同的方法?
解决方案
当有多个可以调用的重载时,Java 选择最具体的适用方法:
非正式的直觉是,如果第一个方法处理的任何调用都可以传递给另一个方法而不会出现编译时错误,那么一个方法比另一个方法更具体。在诸如显式类型化的 lambda 表达式参数(第 15.27.1 节)或变量 arity 调用(第 15.12.2.4 节)等情况下,允许有一定的灵活性以使一个签名适应另一个签名。
toString(Collection<Object>)
不适用于 a List<Integer>
,因为aList<Integer>
不是 aList<Object>
,所以它也不是 a Collection<Object>
。因此,只有toString(Object)
方法是适用的,所以这就是被调用的方法。
toString(Collection<Object>)
适用于,List.of(someInteger)
因为那List.of
是一个多表达式:它可能是List<Integer>
,它可能是List<Object>
,它可能是List<Serializable>
。
由于两者toString(Object)
和toString(Collection<Object>)
都适用,它必须选择一个或另一个(或声明它是模棱两可的)。Collection
重载更具体,因为:
- 你传递给的任何东西
toString(Collection<Object>)
也可以传递给toString(Object)
- 但是有些东西可以传递给
toString(Object)
不能传递给toString(Collection<Object>)
(例如new Object()
)。
这使得toString(Collection<Object>)
更具体,所以这是选择的。
推荐阅读
- memory - 最好在堆栈上分配太多内存,还是在堆上分配正确的数量?
- c - 汇编中的C函数调用问题
- react-native - Expo React-Native App 在作为独立 APK 运行时不起作用
- html - R - 丹麦议会的 DOM 问题(网络抓取)
- android-databinding - LiveData vs Observable 数据对象
- regex - 正则表达式:用空格替换点后跟单词
- spring-mvc - 控制器中映射的url路径
- google-cloud-platform - 无法调试气流错误。尝试使用气流在 GCP 上构建数据管道
- c++ - 枚举中 ALL 标志的紧凑非重复方式,表示 C++ 中的位标志
- c - 通过给定的扫描集在 scanf() 检测太长的字符串