首页 > 解决方案 > 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静态选择不同的方法?

标签: javagenericsjava-11overload-resolutionstatic-polymorphism

解决方案


当有多个可以调用的重载时,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>)更具体,所以这是选择的。


推荐阅读