Reputation: 421
The JVM spec (5.4.3.3) describes how method resolution is done for method refs. If it cannot find a method in a class or its superclasses, it tries to find the method in the superinterfaces.
What is the reason for this? Wouldn't a method declared by a superinterface be listed in the constant pool as an interface method ref instead of a method ref?
My understanding is that method refs are used in invokevirtual
operations, whereas interface method refs are used in invokeinterface
operations. I don't see how one could invoke an interface method using invokevirtual <methodref>
.
Upvotes: 6
Views: 144
Reputation: 15163
Why not?
You can invoke .stream()
on an ArrayList<>
just fine. In fact, the following snippet
ArrayList<Object> arr = new ArrayList<>();
arr.stream();
will be compiled to
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;
But ArrayList<>
(or any of it's superclasses) don't have a .stream()
method.
The method implementation that is used is from the interface Collection
:
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
But if, at any point, ArrayList<>
decides that it can provide a better .stream()
method, then you don't want to compile your code again.
Also the implementation (or non-implementation) of the .stream()
method would leak through, and it's better to avoid that.
Upvotes: 5