MattDs17
MattDs17

Reputation: 421

Why does the JVM consider superinterfaces when resolving non-interface methods? (JVM 5.4.3.3)

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

Answers (1)

Johannes Kuhn
Johannes Kuhn

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

Related Questions