为什么Java在编译时绑定变量? [英] Why does Java bind variables at compile time?

查看:121
本文介绍了为什么Java在编译时绑定变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下示例代码

class MyClass {
    public String var = "base";

    public void printVar() {
        System.out.println(var);
    }
}

class MyDerivedClass extends MyClass {
    public String var = "derived";

    public void printVar() {
        System.out.println(var);
    }
}

public class Binding {
    public static void main(String[] args) {
        MyClass base = new MyClass();
        MyClass derived = new MyDerivedClass();

        System.out.println(base.var);
        System.out.println(derived.var);
        base.printVar();
        derived.printVar();
    }
}

它提供以下输出

base
base
base
derived

在运行时解析方法调用,并按预期调用正确的重写方法。

变量访问在编译时被解析,因为我后来才知道。
我原以为输出为

Method calls are resolved at runtime and the correct overridden method is called, as expected.
The variables access is instead resolved at compile time as I later learned. I was expecting an output as

base
derived
base
derived

因为在派生类中重新定义 var 隐藏基类中的那个。

为什么变量的绑定发生在编译时而不是在运行时?这仅仅是出于性能原因吗?

because in the derived class the re-definition of var shadows the one in the base class.
Why does the binding of variables happens at compile time and not at runtime? Is this only for performance reasons?

推荐答案

原因在Java语言规范的第15.11节,引用如下:

The reason is explained in the Java Language Specification in an example in Section 15.11, quoted below:


...

...

最后一行显示,实际上,访问的字段不依赖于在引用对象的运行时类;即使 s 包含对类 T 的对象的引用,表达式 sx 指的是 S 类的 x 字段,因为表达式的类型 s S 。 T类的对象包含两个名为 x 的字段,一个用于类 T ,另一个用于其超类 S

The last line shows that, indeed, the field that is accessed does not depend on the run-time class of the referenced object; even if s holds a reference to an object of class T, the expression s.x refers to the x field of class S, because the type of the expression s is S. Objects of class T contain two fields named x, one for class T and one for its superclass S.

缺少对字段访问的动态查找,可以使程序高效运行直截了当的实施。可以使用后期绑定和覆盖的功能,但仅在使用实例方法时 ...

This lack of dynamic lookup for field accesses allows programs to be run efficiently with straightforward implementations. The power of late binding and overriding is available, but only when instance methods are used...

所以是的表现是一个原因。如何评估字段访问表达式的规范如下:

So yes performance is a reason. The specification of how the field access expression is evaluated is stated as follows:



  • 如果字段不是静态

...


  • 如果该字段是非空 final ,则结果是 T类型中指定成员字段的值主要的值引用的对象中找到。

  • If the field is a non-blank final, then the result is the value of the named member field in type T found in the object referenced by the value of the Primary.

其中 Primary 在你的情况下引用变量派生这是类型 MyClass

where Primary in your case refers the variable derived which is of type MyClass.

正如@Clashsoft建议的那样,另一个原因是,在子类中,字段未被覆盖,他们隐藏。因此,允许根据声明的类型或使用强制转换来访问哪些字段是有意义的。对于静态方法也是如此。这就是根据声明的类型确定字段的原因。与实例方法的覆盖不同,它取决于实际类型。上面的JLS引用确实隐含地提到了这个原因:

Another reason, as @Clashsoft suggested, is that in subclasses, fields are not overriden, they are hidden. So it makes sense to allow which fields to access based on the declared type or using a cast. This is also true for static methods. This is why the field is determined based on the declared type. Unlike overriding by instance methods where it depends on the actual type. The JLS quote above indeed mentions this reason implicitly:


可以使用后期绑定和覆盖的强大功能,但仅限于实例方法使用。

这篇关于为什么Java在编译时绑定变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆