为什么 JVM 在解析非接口方法时会考虑超接口? (JVM 5.4.3.3)
Why does the JVM consider superinterfaces when resolving non-interface methods? (JVM 5.4.3.3)
JVM 规范 (5.4.3.3) 描述了如何为方法引用完成方法解析。如果它无法在 class 或其超类class 中找到方法,它会尝试在超接口中找到该方法。
这是什么原因?超接口声明的方法不会被列在常量池中作为接口方法引用而不是方法引用吗?
我的理解是方法引用用于invokevirtual
操作,而接口方法引用用于invokeinterface
操作。我不明白如何使用 invokevirtual <methodref>
调用接口方法。
为什么不呢?
您可以在 ArrayList<>
上调用 .stream()
就好了。事实上,下面的片段
ArrayList<Object> arr = new ArrayList<>();
arr.stream();
将编译为
0: new #16 // class java/util/ArrayList
3: dup
4: invokespecial #18 // Method java/util/ArrayList."<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #19 // Method java/util/ArrayList.stream:()Ljava/util/stream/Stream;
但是 ArrayList<>
(或其任何超类)没有 .stream()
方法。
使用的方法实现来自 interface Collection
:
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
但是,如果 ArrayList<>
在任何时候决定它可以提供更好的 .stream()
方法,那么您就不想再次编译您的代码。
.stream()
方法的实现(或未实现)也会泄漏,最好避免这种情况。
JVM 规范 (5.4.3.3) 描述了如何为方法引用完成方法解析。如果它无法在 class 或其超类class 中找到方法,它会尝试在超接口中找到该方法。
这是什么原因?超接口声明的方法不会被列在常量池中作为接口方法引用而不是方法引用吗?
我的理解是方法引用用于invokevirtual
操作,而接口方法引用用于invokeinterface
操作。我不明白如何使用 invokevirtual <methodref>
调用接口方法。
为什么不呢?
您可以在 ArrayList<>
上调用 .stream()
就好了。事实上,下面的片段
ArrayList<Object> arr = new ArrayList<>();
arr.stream();
将编译为
0: new #16 // class java/util/ArrayList
3: dup
4: invokespecial #18 // Method java/util/ArrayList."<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #19 // Method java/util/ArrayList.stream:()Ljava/util/stream/Stream;
但是 ArrayList<>
(或其任何超类)没有 .stream()
方法。
使用的方法实现来自 interface Collection
:
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
但是,如果 ArrayList<>
在任何时候决定它可以提供更好的 .stream()
方法,那么您就不想再次编译您的代码。
.stream()
方法的实现(或未实现)也会泄漏,最好避免这种情况。