From following sources:
https://www.amazon.com/Java-Complete-Reference-Herbert-Schildt/dp/0071808558
Chapter 8 : Using final with Inheritance
http://javarevisited.blogspot.com.by/2012/03/what-is-static-and-dynamic-binding-in.html
Static Vs. Dynamic Binding in Java
for private,static,final methods early(static) method binding should be used
. So I've created a little test
class MethodRefDemo2
{
public static void main( String args[] )
{
BindingTest bindingTest = new BindingTest();
bindingTest.printEarly();
bindingTest.printLate();
}
}
class BindingTest
{
private String early = "static";
private String late = "dynamic";
final String printEarly()
{
return early;
}
String printLate()
{
return late;
}
}
So as I think, these two methods should have different binding types. Checking byte code:
public static main([Ljava/lang/String;)V
L0
LINENUMBER 8 L0
NEW spring/BindingTest
DUP
INVOKESPECIAL spring/BindingTest.<init> ()V
ASTORE 1
L1
LINENUMBER 9 L1
ALOAD 1
INVOKEVIRTUAL spring/BindingTest.printEarly ()Ljava/lang/String;
POP
L2
LINENUMBER 10 L2
ALOAD 1
INVOKEVIRTUAL spring/BindingTest.printLate ()Ljava/lang/String;
POP
L3
LINENUMBER 11 L3
RETURN
L4
LOCALVARIABLE args [Ljava/lang/String; L0 L4 0
LOCALVARIABLE bindingTest Lspring/BindingTest; L1 L4 1
MAXSTACK = 2
MAXLOCALS = 2
Here i see two INVOKEVIRTUAL instructions. So is there any way to determine what kind of binding was used by the class byte code? And if no, how can i determine binding type?
答案 0 :(得分:2)
短语“来自Java规范”具有误导性,因为没有多个规范,因此只有the Java specification不包含引用的语句。
术语“早期绑定”和“后期绑定”不足以描述Java方法调用的可能性。
唯一在编译时解析其最终目标的方法调用是private
方法和构造函数调用,以及自{8}以来static
类interface
方法调用。
对于非static
类型和interface
方法调用的super
方法调用,将在编译时设置目标类型,但JVM可以解析运行时指定类型的超类型的方法。尽管如此,解析后的目标方法在特定运行时永远不会改变,并且不需要为每个方法调用进行解析,因此一旦方法得到解决,它就是某种早期绑定。但是JVM通常会将解析推迟到调用指令的第一次实际执行。
对于剩余的实例方法调用类型,目标方法是否在编译时声明为final
并不重要。这些调用总是以与invokevirtual
指令相同的方式编码,这意味着根据接收器对象类型查找实际的目标方法。在编译调用者之后,您可以将方法更改为final
或非final
,而不会破坏兼容性(除非您覆盖之后转为final
的方法)。
当接收器类型为interface
时,在编译时永远不会将其视为final
,但仍会在运行时以final
方式结束。
当然,在解析之后,JVM可能会注意到目标方法已被声明为final
并转向与上述第二种类型的“早期绑定”匹配的优化调用,另一方面,大多数JVM都是足够聪明,可以使用尚未声明final
但仍未实际覆盖的方法(可能适用于大多数方法)。因此,如果唯一的结果是应用于其他方法的优化,则调用final
方法“早期绑定”的调用是毫无意义的。