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>
.
The process of compiler trying to resolve the method call from given overloaded method definitions is called overload resolution. If the compiler can not find the exact match it looks for the closest match by using upcasts only (downcasts are never done).
This information is basically stored in the run-time constant pool. So when the JVM starts execution, it will use those symbolic references to locate those classes and it's components in the classloader. So resolving is a process of converting these symbolic references to their actually references.
Initially when a JVM starts up, nothing is loaded into it. The class file of the program being executed is loaded first and then other classes and interfaces are loaded as they get referenced in the bytecode being executed.
Method Area. The Java Virtual Machine has a method area that is shared among all Java Virtual Machine threads. The method area is analogous to the storage area for compiled code of a conventional language or analogous to the "text" segment in an operating system process.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With