2

I would like to clarify a few things about binding and dispatch.

Binding is attaching a method call to a method signature. Dispatch is choosing over method implementations. First comes binding, then comes dispatch. OK, I got this, but:

  1. Do instance methods that have not been overridden use static binding?
  2. Why exactly do overloaded methods use static binding since they are virtual and can be overridden in subclasses?

I've read lots of explanations over the last few days and it's a mess for me now. Some of them are conflicting or completely opposite from one another. From what I know all non-static, non-private and non-final methods in Java are virtual by default and must use dynamic binding and dynamic dispatch.

  • 1. No. Coz it may be overridden by someone else. Compiler won't know a method is not overridden. Exception is private method and final method, for which at least the former is statically bind. 2. What makes you think "overloaded method use static bind"? – Adrian Shum Sep 07 '17 at 09:57

2 Answers2

2

Binding is attaching a method call to a method signature. Dispatch is choosing over method implementations.

Binding in the sense you mean refers to overloading. Dispatch in the sense you mean refers to overriding.

First comes binding, then comes dispatch.

Yes. The compiler does the binding, the JVM does dispatching.

OK, I got this, but:

  1. Do instance methods that have not been overridden use static binding?

No. The compiler can't tell that, except in the case of private methods, in which case it uses the invokespecial bytecode.

  1. Why exactly do overloaded methods use static binding since they are virtual and can be overridden in subclasses?

They don't.

From what I know all non-static, non-private and non-final methods in Java are virtual by default and must use dynamic binding and dynamic dispatch.

Correct.

Community
  • 1
  • 1
user207421
  • 305,947
  • 44
  • 307
  • 483
  • Now I understand that overloaded methods, being virtual, use dynamic binding during runtime, but: 3) Overloaded methods are bonded using static binding while overridden methods are bonded using dynamic binding at runtime. What's meant by that? – violet_eyes Sep 07 '17 at 14:30
  • @violet_eyes I have seen this statement "Overloaded methods are bonded using static binding while overridden methods are bonded using dynamic binding at runtime." on few blogs, but this statement is not always True. It all depends on the way method has been called and declared. You can see the case I have provided in my answer where overloaded method is dynamically bonded. – Raman Kumar Sharma Sep 08 '17 at 04:13
  • This part seems wrong: _No. The compiler can't tell that, except in the case of private or final methods._ There is only one bytecode: `invokevirtual` to call non-static, non-interface methods at compile time, even for `private/final` methods, so the compile-time behavior is the same. During runtime compilation (JIT), `final` and `private` also don't help on any modern JVM does _class hierarchy analysis_ to determine whether there a any overriding methods, regardless of the presence of `final` or `private`. So in practice these qualifiers are not changing the behavior at compile or runtime. – BeeOnRope Sep 08 '17 at 04:25
  • @EJP - see also my comments to Raman below: even for `final` and `private` methods, the compile-time binding is dynamic: you have only the `invokevirtual` bytecode. There simply is no way to express in the `.class` file "call this method as implemented in this class, and **never** any overriding method in a subclass". So even if the compiler can guess that a method can't be overridden, it still does dynamic binding (and as shown below, the guess can be wrong since classes can change). – BeeOnRope Sep 08 '17 at 19:21
  • @BeeOnRope `invokevirtual` is not emitted in the case of `private` or `final` methods. There are other bytecodes for invocation. – user207421 Sep 26 '18 at 10:19
  • @user207421 - I think we are each half right. For `private` methods, you are right: the `invokespecial` bytecode is used. This is because `private` methods can't be called except from within the same class, so there is no chance of inconsistency at compile-time versus runtime. For `final` methods, however, I think I am right: the `invokevirtual` method is still used. Probably because `final` at compile time doesn't necessarily mean `final` at runtime, since the target class might have changed. I've edited the answer to reflect that. – BeeOnRope Sep 26 '18 at 19:48
0

Rules for binding in java:

1) Call to a Static method is Statically binded.

2) Call to a constructor is statically binded.

3) Call to non-static methods are dynamically binded:

Exceptions: 3.a) Call to private , non-static method is statically binded.

3.b) non-private, non-static method called using super in subclass is also statically binded.

So for 1st question i.e. Do instance methods that have not been overridden use static binding?

Answer is No. If the method has not been overridden, but it can be(in future). And as it is an instance method it can be called using instance(dynamic binding) or invoked using super (static binding).

2nd question: Why exactly do overloaded methods use static binding since they are virtual and can be overridden in subclasses?

Answer: There is no such thing that overloaded methods are statically binded.

Explanation:

class Sample{

    public void method1(){
        System.out.println("hello from A");
    }

    public void method1(String user){
        System.out.println("hello "+user+" from overloaded method");
    }

        public static void main(String []argh){ 
        Sample s = new Sample();
        s.method1();
        s.method1("name");
    }
}

In the above code, the method method1() is overloaded but since it is neither static,final nor private, so it generates invokevirtual instruction, which means it is dynamically binded not static.

To clear the difference of binding and Dispatching refer this Question

  • 1
    `final` methods are not statically bound at compile-time. Try this [experiment](https://gist.github.com/travisdowns/92e85659cc9680df82fb0b9a98e11193). Put `Base`, `Derived` and `Print` in there own files and compile `Base` and `Print` with `javac`. Now `Print.printBase` should be _statically binding the call to `Base.print()` since that call is `final`. Move the `Print.class` away somewhere, and now remove the `final` modifier from `Base.print()`. Compile `Derived` (this will also compile `Base` and `Print` since `javac` compiles dependencies. – BeeOnRope Sep 08 '17 at 06:12
  • Finally, copy back the version "statically bound" version of `Print.class` that you compiled originally (replacing the newest one). Run the `main()` in `Derived`. Note that it prints `"derived"`. There was no static binding despite print being compiled against `final Base.print()`. You can confirm this with `javap` - the bytecode generated uses `invokevirtual` to call `print()` _regardless of whether the method called is final or not_. In fact, this is the _only_ bytecode used to call non-static, non-interface methods, so there cannot be such a thing as static binding at compile time. – BeeOnRope Sep 08 '17 at 06:15
  • Earlier I didn't write `final` in my answer, but then some books confused me. In Java, the Complete reference it is mentioned that "since final methods cannot be overridden, a call to one can be resolved at compile time. This is called early binding", also in "Thinking in Java" it's there that "All method binding in Java uses late binding unless the method is static or final" THANKS for making it clear that binding doesn't depend on `final`. – Raman Kumar Sharma Sep 08 '17 at 08:36
  • Well I'm not sure what those books are talking about, but there is _no such mechanism_ in the JVM spec for _static_ binding of normal method calls. There literally is only one instruction for method calls: `invokevirtual` so there is only one type of binding, which is dynamic binding. It's not specific to `final` - you can do the same thing with `private`, although it's harder because verification will fail if you try to override a `private` method, but the fact remains that you can compile some code that calls a `private` method, and at runtime it may call an implementation in a subclass! – BeeOnRope Sep 08 '17 at 19:19