java – 存在的方法……不是吗?
作者:互联网
代码(编译):
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实现了Iterable.)
解决方法:
两种方法在编译时都兼容.但运行时是另一种野兽.我假设您的代码针对较旧版本的Google Collections进行编译,但针对较新版本运行.
编辑:
详细情况:
鉴于线条
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);
在这两种情况下,Java只使用完全给定的类型执行查找.它不执行类似“可以使用给定类型调用的返回方法”的搜索.
在您的情况下,运行时类路径和编译时类是不同的.因此类加载器/链接器无法执行查找.
退一步
此问题显示了不同级别的兼容性:
>二进制兼容性:扔进一个新罐子就是这样.
>源兼容性:您必须编译源代码,但不必更改它.
>行为兼容性或语义兼容性:必须更改客户端代码.
您可以使用这些关键字浏览此网站或Google以获取更多信息.二进制兼容性的一个很好的参考是Evolving Java-based APIs的三个部分.
标签:nosuchmethoderror,java,guava,classpath 来源: https://codeday.me/bug/20190826/1732718.html