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>)不适用于List<Integer>,因为List<Integer>不是List<Object>,所以它也不是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>)更具体,因此这是选择的那个。

最新更新