Java静态多态(重载)和泛型之间的继承

gav*_*koa 5 java generics overload-resolution static-polymorphism java-11

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))));
}
Run Code Online (Sandbox Code Playgroud)

令人惊讶的输出:

// from toString(Object)
ImmutableCollections.List12[e0=1,e1=<null>]
// from toString(Collection<Object>)
[Integer[value=1]]
Run Code Online (Sandbox Code Playgroud)

为什么Java静态选择不同的方法?

And*_*ner 11

当可以调用多个重载时,Java 会选择最具体的适用方法

非正式的直觉是,如果第一个方法处理的任何调用都可以传递给另一个方法而没有编译时错误,则一个方法比另一个方法更具体。在诸如显式类型化的 lambda 表达式参数(第 15.27.1 节)或变量参数调用(第 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>)更具体,所以这是被选择的。

  • 作为附录,问题的可能预期解决方案是将签名更改为“toString(Collection&lt;?&gt; collection)”…… (3认同)