【问题标题】:Java dynamic vs static binding [duplicate]Java动态与静态绑定[重复]
【发布时间】:2015-11-06 19:36:11
【问题描述】:

我有一个关于动态与静态的简单问题。因此,根据我的阅读,静态绑定适用于私有、最终、重载、静态方法,它依赖于引用的类型。例如,动态方法不是私有的、最终的、重载的,并且依赖于对象的类型。

如果你做Human myobj = new Boy();之类的事情,哪个是引用的类型,哪个是对象的类型?

【问题讨论】:

  • 所以...您认识到静态和动态绑定适用于方法,但随后询问有关对象和引用的问题?
  • 我不是专家,但我相信您的示例也是静态的。所有信息在编译时都可用,因此编译器应该能够执行所有必要的检查。引用的类型是Human,对象的类型是Boy,就像锡上说的一样。

标签: java dynamic methods binding static


【解决方案1】:

您的关于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的文档:

调用类(静态)方法

来自invokespecial的文档:

调用实例方法;对超类、私有和实例初始化方法调用的特殊处理

来自invokevirtual的文档:

调用实例方法; 基于类的调度

“Dispatch based”表示动态绑定,其他两个为静态绑定。

还有两个调用指令:

  • invokeinterface:类似于invokevirtual,但在接口引用上,而不是在类引用上。
  • invokedynamic:主要用于动态(脚本)语言,例如 Groovy,并且“就像通过执行 invokevirtual 指令一样被调用”。

【讨论】:

    【解决方案2】:

    Java 中的静态绑定发生在编译时,而动态绑定发生在运行时,因此您的类型是 Human,而对象的类型(例如,如果您使用 instanceof)将是 Boy。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多