Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Java bind variables at compile time?

Consider the following example code

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();     } } 

it gives the following output

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 

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?

like image 642
Alessandro Da Rugna Avatar asked Sep 06 '15 11:09

Alessandro Da Rugna


People also ask

Why static methods are early binding?

Hence compiler doesn't have any difficulty determining the object of the class (local class for sure). That's the reason binding for such methods is static. It takes place at runtime so do it is referred to as late binding. It uses overriding methods.

Why static binding is used in polymorphism in Java?

Polymorphism allows an object to take multiple forms – when a method exhibits polymorphism, the compiler has to map the name of the method to the final implementation. If it's mapped at compile time, it's a static or early binding. If it's resolved at runtime, it's known as dynamic or late binding.

Why we need dynamic binding?

Dynamic binding allows us to ignore the type differences by providing us with the flexibility in choosing which type of function we need at that instant of runtime. On examining this statement, we can understand that dynamic binding allows us to handle different objects using just a single function name.

Why inheritance is compile time?

inheritance is always achieched at compile time. the code acquires reusability with extends keyword even before entering into jvm for verification and thus converting to bytecode,although we can only use its features at run-time after the creation of the object.

What is binding in Java?

Connecting a method call to the method body is known as binding. Static Binding (also known as Early Binding). Dynamic Binding (also known as Late Binding). Let's understand the type of instance. Each variable has a type, it may be primitive and non-primitive. Here data variable is a type of int.

What is the difference between static and dynamic binding in Java?

Static vs Dynamic Binding in Java. Static Binding: The binding which can be resolved at compile time by compiler is known as static or early binding. Binding of all the static, private and final methods is done at compile-time .

What is binding in C++?

Connecting a method call to the method body is known as binding. Static Binding (also known as Early Binding). Dynamic Binding (also known as Late Binding). Let's understand the type of instance. Each variable has a type, it may be primitive and non-primitive.

What is the difference between data variable and object in Java?

Each variable has a type, it may be primitive and non-primitive. Here data variable is a type of int. An object is an instance of particular java class,but it is also an instance of its superclass. Here d1 is an instance of Dog class, but it is also an instance of Animal.


2 Answers

While you might be right about performance, there is another reason why fields are not dynamically dispatched: You wouldn't be able to access the MyClass.var field at all if you had a MyDerivedClass instance.

Generally, I don't know about any statically typed language that actually has dynamic variable resolution. But if you really need it, you can make getters or accessor methods (which should be done in most cases to avoid public fields, anyway):

class MyClass {     private String var = "base";      public String getVar() // or simply 'var()'     {         return this.var;     } }  class MyDerivedClass extends MyClass {     private String var = "derived";      @Override     public String getVar() {         return this.var;     } } 
like image 37
Clashsoft Avatar answered Oct 07 '22 00:10

Clashsoft


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

...

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:

  • If the field is not static:

    ...

    • 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.

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

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:

The power of late binding and overriding is available, but only when instance methods are used.

like image 157
M A Avatar answered Oct 07 '22 00:10

M A