|
|
|
Advertisement
|
Other forms of method invocation
Although instance methods normally are invoked with
invokevirtual, two other opcodes are used to invoke this
kind of method in certain situations: invokespecial and
invokeinterface.
Invokespecial is used in three situations in which an
instance method must be invoked based on the type of the reference, not
on the class of the object. The three situations are:
<init>)
methods
super keyword
Invokeinterface is used to invoke an instance method given
a reference to an interface.
| Opcode | Operand(s) | Description |
|---|---|---|
invokespecial |
indexbyte1, indexbyte2 |
pop objectref and args, invoke method at constant pool index |
invokeinterface |
indexbyte1, indexbyte2 |
pop objectref and args, invoke method at constant pool index |
The invokespecial instruction
Invokespecial differs from invokevirtual
primarily in that invokespecial selects a method based on
the type of the reference rather than the class of the object. In other
words, it does static binding instead of dynamic binding. In each of
the three situations where invokespecial is used, dynamic
binding wouldn't yield the desired result.
invokespecial and <init>
The compiler places code for constructors and instance variable
initializers into <init> methods, or instance
initialization methods. A class gets one <init>
method in the class file for each constructor in the source. If you
don't explicitly declare a constructor in the source, the compiler will
generate a default no-arg constructor for you. This default constructor
also ends up as an <init> method in the class file.
So just as every class will have at least one constructor, every class
also will have at least one <init> method.
The <init> methods are called only when a new
instance is created. At least one <init> method will
be invoked for each class along the inheritance path of the newly
created object, and multiple <init> methods could be
invoked for any one class along that path.
Why is invokespecial used to invoke
<init> methods? Because subclass
<init> methods need to be able to invoke superclass
<init> methods. This is how multiple
<init> methods get invoked when an object is
instantiated. The virtual machine invokes an <init>
method declared in the object's class. That <init>
method first invokes either another <init> method in
the same class, or an <init> method in its
superclass. This process continues all the way up to
Object.
For example, consider this code:
class Dog {
}
class CockerSpaniel extends Dog {
public static void main(String args[]) {
CockerSpaniel bootsie = new CockerSpaniel();
}
}
When you invoke main(), the virtual machine will allocate
space for a new CockerSpaniel object, then invoke
CockerSpaniel's default no-arg <init>
method to initialize that space. That method will invoke
Dog's <init> method, which will invoke
Object's <init> method.
Because every class has at least one <init> method,
it is common for classes to have <init> methods with
identical signatures. (A method's signature is its name and
the number and types of its arguments.) For example, the
<init> methods for all three classes in the
inheritance path for CockerSpaniel have the same
signature. CockerSpaniel, Dog, and
Object all contain a method named
<init> that takes no arguments.
It would be impossible to invoke a Dog's
<init> method from CockerSpaniel's
<init> method using invokevirtual,
because invokevirtual would perform dynamic binding and
invoke CockerSpaniel's <init> method.
With invokespecial, however, Dog's
<init> method can be invoked from
CockerSpaniel's <init> method, because
the type of the reference placed in the class file is
Dog.
|
Sponsored Links
|