3

代码(编译):

    for (Method m : ImmutableList.class.getMethods()) {
        System.out.println(m);
    }

    ImmutableList.copyOf(Arrays.asList(new PlayerLevel[0]));

输出(带注释和缩短):

public final void com.google.common.collect.ImmutableList.add(int,java.lang.Object)
----> public static com.google.common.collect.ImmutableList com.google.common.collect.ImmutableList.copyOf(java.lang.Iterable)
public static com.google.common.collect.ImmutableList com.google.common.collect.ImmutableList.copyOf(java.util.Iterator)
                 (lots of other methods)

java.lang.NoSuchMethodError: com.google.common.collect.ImmutableList.copyOf(Ljava/util/Collection;)Lcom/google/common/collect/ImmutableList;

嗯?

(如果日志不够清晰,我会收到一条错误消息,说这ImmutableList.copyOf(List)不是一种方法,而是通过循环遍历我看到的所有方法,有一个copyOf(Iterable), 和List implements Iterable。)

4

1 回答 1

6

这两种方法在编译时是兼容的。但运行时是另一种野兽。我假设您的代码针对旧版本的 Google 收藏集进行编译,但针对新版本运行。

编辑:详细情况:

鉴于线条

List<String tmpArray = Arrays.asList(new PlayerLevel[0]);
ImmutableList.copyOf(tmpArray);

编译器开始寻找ImmutableList名称copyOf和参数与静态类型兼容List<String>的合适方法。编译器可见的类的版本提供了完全匹配:

ImmutableList.copyOf(Collection<T> arg0);

请注意,编译器对 的实际类型感兴趣,只考虑静态类型(又名“正式类型”)。tmpArray

编译器将所选方法的签名写入类文件。

在运行时,类加载器/链接器读取类,找到方法的签名

ImmutableList.copyOf(Collection<T> arg0);

并对给定的签名执行查找(不是搜索!)ImmutableList兼容性在这里并不重要,那是编译器的工作。如果你像这样使用反射,你会得到相同的结果:

ImmutableList.class.method("copyOf", Collection.class);

In both cases Java simply performs a lookup using exactly the given type. It does not perform a search like "return method(s) which can be called with the given type".

In your case the runtime classpath and the compile time class are different. So the classloader / linker fails to perform the lookup.

One step back

This issue shows the different levels of compatibility:

  • Binary compatibility: Throw in a new jar and that's it.
  • Source compatibility: You have to compile your source but you don't have to change it.
  • Behavioural compatibility or Semantic compatibility: The client code must be changed.

You can use these keywords to look around this site or on Google for more infos. A good reference for binary compatibility are the three parts of Evolving Java-based APIs.

于 2011-11-04T15:16:22.413 回答