我有一个关于动态与静态的简单问题。因此,根据我的阅读,静态绑定(bind)适用于私有(private)、最终、重载、静态方法,并且它依赖于引用的类型。例如,动态方法不是私有(private)的、最终的、重载的,并且依赖于对象的类型。
如果您执行类似 Human myobj = new Boy();
的操作,哪个是引用类型,哪个是对象类型?
最佳答案
您关于final
和重载的说法不正确。不知道你在哪里读到的。
使用 Java 8 (1.8.0_51) 编译以下代码。
public class Test {
public static void main(String[] args) {
Test x = new Test();
x.a();
x.b();
x.c();
x.d(1);
x.d(1L);
x.d(1d);
x.d(null);
}
private void a() {}
public final void b() {}
public static void c() {}
private void d(int x) {}
public final void d(long x) {}
public static void d(double x) {}
public void d(String x) {}
}
注意:使用实例变量调用静态方法是不好的形式。应该使用类名来完成,因此是显式静态的。代码使用实例变量仅用于说明目的。
反编译字节码显示:
0: new #1 // class test/Test
3: dup
4: invokespecial #19 // Method "<init>":()V
7: astore_1
8: aload_1
9: invokespecial #20 // Method a:()V
12: aload_1
13: invokevirtual #23 // Method b:()V
16: invokestatic #26 // Method c:()V
19: aload_1
20: iconst_1
21: invokespecial #29 // Method d:(I)V
24: aload_1
25: lconst_1
26: invokevirtual #33 // Method d:(J)V
29: dconst_1
30: invokestatic #36 // Method d:(D)V
33: aload_1
34: aconst_null
35: invokevirtual #39 // Method d:(Ljava/lang/String;)V
38: return
私有(private)
方法a()
和d(int)
被专门调用。
static
方法 c()
和 d(double)
是静态调用的。
其余方法 b()
、d(long)
和 d(String)
是虚拟调用的。
如您所见,final
和重载不会影响结果。
来自 invokestatic
的文档:
Invoke a class (static) method
来自 invokespecial
的文档:
Invoke instance method; special handling for superclass, private, and instance initialization method invocations
来自 invokevirtual
的文档:
Invoke instance method; dispatch based on class
“Dispatch based”表示动态绑定(bind),另外两个是静态绑定(bind)。
还有两个调用指令:
-
invokeinterface
:与invokevirtual
类似,但基于接口(interface)引用,而不是类引用。 -
invokedynamic
:主要用于动态(脚本)语言,例如 Groovy,“就像通过执行invokevirtual
指令来调用”。
关于Java 动态绑定(bind)与静态绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33574371/