📜  Java中的静态绑定与动态绑定

📅  最后修改于: 2020-03-22 13:30:49             🧑  作者: Mango

静态绑定: 可以在编译时由编译器解析的绑定称为静态绑定或早期绑定。所有静态,私有和最终方法的绑定都在编译时完成。
为什么绑定静态,最终和私有方法始终是静态绑定? 
静态绑定是更好的性能选择(不需要额外的开销)。编译器知道所有此类方法都不能被覆盖,并且始终由本地类的对象访问。因此,编译器确定类的对象(肯定是本地类)没有任何困难。这就是此类方法的绑定是静态的原因。
让我们看一个例子

public class NewClass {
    public static class superclass {
        static void print()
        {
            System.out.println("父类.");
        }
    }
    public static class subclass extends superclass {
        static void print()
        {
            System.out.println("子类.");
        }
    }
    public static void main(String[] args)
    {
        superclass A = new superclass();
        superclass B = new subclass();
        A.print();
        B.print();
    }
}

在向下滚动之前,猜猜上面程序的输出吗?
输出

父类.
父类.

如您所见,在两种情况下都将调用超类的打印方法。让我们看看这是怎么发生的

  • 我们使用超类的引用创建了一个子类对象和一个超类对象。
  • 由于超类的打印方法是静态的,因此编译器知道它不会在子类中被覆盖,因此编译器知道在编译期间要调用哪种打印方法,因此不会产生歧义。

作为练习,读者可以将对象B的引用更改为子类,然后检查输出。

动态绑定: 在动态绑定中,编译器不会确定要调用的方法。重写是动态绑定的完美示例。在重写中,父类和子类都具有相同的方法。让我们看一个例子

public class NewClass {
    public static class superclass {
        void print()
        {
            System.out.println("父类.");
        }
    }
    public static class subclass extends superclass {
        @Override
        void print()
        {
            System.out.println("子类.");
        }
    }
    public static void main(String[] args)
    {
        superclass A = new superclass();
        superclass B = new subclass();
        A.print();
        B.print();
    }
}

输出:

父类.
子类.

这里的输出不同。但为什么?让我们分解代码并彻底理解它。

  • 方法在此代码中不是静态的。
  • 在编译期间,编译器不知道必须调用哪个打印,因为编译器仅通过引用变量而不是按对象类型进行引用,因此绑定将延迟到运行时,因此将根据类型调用相应的打印版本在对象上。

重要事项

  • 私有,最终和静态成员(方法和变量)使用静态绑定,而对于虚拟方法(在Java方法中默认为虚拟),绑定是在运行时根据运行时对象完成的。
  • 静态绑定使用类型信息进行绑定,而动态绑定使用对象来解析绑定。
  • 使用静态绑定解析重载的方法(确定存在多个具有相同名称的方法时,决定调用哪个方法),而使用动态绑定(即在运行时)则重写重载的方法。