Static/dynamic binding and static/dynamic dispatch are a bit confusing - java

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:
Do instance methods that have not been overridden use static binding?
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.

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

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

Related

Can overloading and overriding in java be static polymorphism as well as dynamic polymorphism?

Well this type of questions have been answered already but this confused me. I have spent lot of time going through lots of answer so please go through my question before making it duplicate.
case 1 -
static polymorphism - function overloading
dynamic polymorphism - function overriding
links -
https://stackoverflow.com/a/12894211/3181738
https://stackoverflow.com/a/20783390/3181738
and many others.
My confusion is that in all the examples dynamic polymorphism is shown using upcasting. What if I don't upcast.
class A{
public void show(){
System.out.print("A");
}
}
class B extends A{
public void show(){
System.out.print("B");
}
public static void main(String[] s){
A a = new B();
a.show(); // upcasting. It is dynamic polymorphism.
B b = new B();
b.show(); // Now java compiler can decide so is it still dynamic polymorphism?
}
}
case 2 -
static polymorphism is achieved via overloading if method is private , static or final.
So what about overloading of public and default methods?
Static methods can only be overloaded.
Non-static methods can be both overridden and overloaded.
public/protected/private doesn't affect this directly, except that since private methods can't be seen from subclasses, they can't be overridden either. The exact rules are defined here
And if you want to prevent the override of a non-static method, you can declare it final. (private methods are therefore implicitly final.)
Q1 upcasting: Upcasting and treating a subclass object as if it were a parent class object is the essence of polymorphism. So your question, "What if I don't upcast?" Then you are not using polymorphism
Q2 static polymorphism - method overridding: This is what it's saying:
static: static methods are overwritable, since they are associated with the class, not the object. So for instance, if you have a class with a main method, and then you subclass that, and add a main method to the subclass, when you execute the main method in the subclass, it is statically overridden
private: private methods are not inherited and cannot be called in the subclass, unless that are statically overridden
final: final methods are not overriddable. Therefore, redefining them in a subclass creates a statically overridden method
Case 1
At compile time, the compiler will identify the method signature that matches ie. it will be show() with no parameters in your example. Whether it is A's or B's method that gets invoked though is still runtime even though in your example you are sure it is a B.
Case 2
I think that the visibility rules of methods maybe causing some confusion for you.
The decision of which overloaded method that will be called at runtime will be decided at compile time ie. overloaded method is statically decided - this is regardless of whether it is public, package-private (default), or private. If the object, in which the method call occurs, does not have visibility of the method it fails at compile time.
As others have said - overriding does not apply to static methods since it is part of the class not the instance.

How does JVM differentiates between method overloading and method overriding internally?

I would like to know how does JVM differentiates between method overloading and method overriding internally.
The JVM only deals with method overriding. A method is overridden by adding a method with the same signature in a derived class (the only allowed difference is in the return type, which is allowed to be more specific). The signature encodes the method's name, as well as the types of the parameters and the return type.
Method overloading means having multiple methods with the same "simple name" but different signatures. At compile time, the javac compiler chooses one of the same-named methods based on the types of the arguments and places its signature in the compiled .class file. A method invocation in compiled Java bytecode must specify the signature of the callee.
Jvm in not involved in method overloading. So it does not have to differentiate between method overloading and method overriding.
You would understand this clearly if you understand how method overloading and method overriding is implemented by Java behind the scenes.
Before going into the difference between overloading and overriding , let us first take a look into Polymorphism .
What is polymorphism ?
Polymorphism is the capability of a method to do different things based on the object that it is acting upon. In other words, polymorphism allows you define one interface and have multiple implementations.
Different types of polymorphism in java.
1) Method Overloading
2) Method Overriding
Types of polymorphism in java: Static, Dynamic, Runtime and Compile time
Now let us come back to the original question and understand the difference between overloading and overriding.
1. The first and most important is that method overloading a compile time polymorphism while method overriding is run time polymorphism. So JVM has to only deal with method overriding . Method overloading is already resolved after compilation.
2.In Method Overloading, methods must have different signature.In Method Overriding, methods must have same signature.
There are many more differences, but above two can really differentiate method overloading from method overriding.
Before winding up let us also look at what each is trying to achieve .
Method Overloading is to “add” or “extend” more to method’s behavior.Method Overriding is to “Change” existing behavior of method.
Method overloading is handled by the compiler (that's why known as static binding) while overriding is handled by JVM.
Overloaded methods are different and can be recognized separately based on the argument list, that's why they get resolved by the compiler at compile time.
Method overriding occurs when we try to call a overridden method on the parent reference which is holding child object. Because we are calling the method on parent reference so at compile time method get resolved from parent reference type so, for the compiler, the method of parent is getting called. But parent is holding the object of child so at runtime method gets called from child.
In order to understand how Java (Compiler + JVM) handles both things internally let's take an example of Mammal and Human class
public class OverridingInternalExample {
private static class Mammal {
public void speak() { System.out.println("ohlllalalalalalaoaoaoa"); }
}
private static class Human extends Mammal {
#Override
public void speak() { System.out.println("Hello"); }
// Valid overload of speak
public void speak(String language) {
if (language.equals("Hindi")) System.out.println("Namaste");
else System.out.println("Hello");
}
#Override
public String toString() { return "Human Class"; }
}
// Code below contains the output and bytecode of the method calls
public static void main(String[] args) {
Mammal anyMammal = new Mammal();
anyMammal.speak(); // Output - ohlllalalalalalaoaoaoa
// 10: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V
Mammal humanMammal = new Human();
humanMammal.speak(); // Output - Hello
// 23: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V
Human human = new Human();
human.speak(); // Output - Hello
// 36: invokevirtual #7 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:()V
human.speak("Hindi"); // Output - Namaste
// 42: invokevirtual #9 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:(Ljava/lang/String;)V
}
}
When we compile above code and try to look at the bytecode using javap -verbose OverridingInternalExample, we can see that compiler generate a constant table where it assigns integer codes to every method call.
I have included the bytecode along with above method calls and by looking at above code we can see that the bytecodes of humanMammal.speak() , human.speak() and human.speak("Hindi") are totally different because the compiler is able to differentiate between them based on the argument list and class reference. And this is why Method Overloading is known as Static Polymorphism or Static Binding.
But bytecode for anyMammal.speak() and humanMammal.speak() is same because according to compiler both methods are called on Mammal reference but the output for both method calls is different because at runtime JVM knows what object the reference is holding and JVM calls the method on the object and this is why Method Overriding is known as Dynamic Polymorphism or simply Polymorphism.
If you want to know more about this you can read more on How Does JVM Handle Method Overloading and Overriding Internally.
Though name of method remains same in case of both method overloading and overriding, main difference comes form the fact that method overloading is resolved during compile time, while method overriding is resolved at runtime. Also rules of overriding or overloading a method is different in Java. For example, private, static and final method cannot be overriding in Java but you can still overload them. For overriding both name and signature of method must remain same, but in for overloading method signature must be different. Last but not the least difference between them is that call to overloaded methods are resolved using static binding while call to overridden method is resolved using dynamic binding in Java. SO JVM is not involved in overloading
Method overloading:
class Calculation{
void sum(int a,int b){System.out.println(a+b);}
void sum(int a,int b,int c){System.out.println(a+b+c);}
}
Method Overriding:
class Calculation{
void sum(){System.out.println("sum in superclass");}
}
class Specific extends Calculation{
void sum(){System.out.println("sum in Specific");}
}

Reducing the visibility of a static method

I know that a child cannot reduce the visibility of a non-static method and I understand why it is so.
I've read however that "static method can be hidden through its redeclaration". I however do not understand how this could be achieved in Java.
Is this really possible? If yes, how to do that (code example) and why was it introduced (it seems to contradict the principle of non-reducing the visibility of the interface)?
The short answer is: no, it is not possible. You have mixed up some terminology. Hiding has nothing to do with accessibility (which is what you are really asking about, not visibility, which is related to scope and shadowing and is discussed in Chapter 6 of the Java Language Specification (JLS)).
Now for the longer answer. The term overriding applies to instance methods, while the term hiding applies to class (static) methods. From the Java Tutorial topic Overriding and Hiding Methods:
The distinction between hiding a static method and overriding an instance method has important implications:
The version of the overridden instance method that gets invoked is the one in the subclass.
The version of the hidden static method that gets invoked depends on whether it is invoked from the superclass or the subclass.
Some of the other answers here provide incorrect examples about method hiding, so let's go back to the JLS, this time to §8.4.8:
Methods are overridden or hidden on a signature-by-signature basis.
That is, to override or hide a method in the parent class, the subclass must define a method with the same signature—basically, the same number and type of arguments (although generics and type erasure makes the rules a little more complicated than that). There are also rules about return types and throws clauses, but those seem irrelevant to this question.
Note that you can define a method in a subclass with the same name as a method in the parent class (or in an implemented interface) but with different number or type of arguments. In that case, you are overloading the method name and neither overriding nor hiding anything; the subclass method is a new method, pretty much independent of the inherited method(s). (There is an interaction when the compiler has to match methods to method calls, but that's about it.)
Now to your question: the terms accessibility and hiding (as well as visibility) are independent concepts in Java. There is, as you put it, a "principle" that there is simply no way for a subclass to reduce the accessibility of an inherited method. This applies regardless of whether you are overriding an instance method or hiding a class method. From the JLS §8.4.8.3:
The access modifier (§6.6) of an overriding or hiding method must provide at least as much access as the overridden or hidden method, as follows:
If the overridden or hidden method is public, then the overriding or hiding method must be public; otherwise, a compile-time error occurs.
If the overridden or hidden method is protected, then the overriding or hiding method must be protected or public; otherwise, a compile-time error occurs.
If the overridden or hidden method has default (package) access, then the overriding or hiding method must not be private; otherwise, a compile-time error occurs.
In summary, the fact that a static method can be hidden has nothing to do with changing the accessibility of the method.
Based on hagubear's valuable comments, it seems that the author of a statement meant hiding a method through overloading it with a method having the same declaration.
Quoting this link:
We can declare static methods with same signature in subclass, but it
is not considered overriding as there won’t be any run-time
polymorphism. (...) If a derived class defines a
static method with same signature as a static method in base class,
the method in the derived class hides the method in the base class.
Thus, defining a method in a child class having exact same declaration effectively hides the original method in child. However, as in case of fields, casting to the parent will restore the original access.
Sample code:
public class Test {
public static void main( String[] args ) {
B b = new B();
A a = b;
b.f(); // "Access somewhat denied"
a.f(); // "f()"
}
}
class A {
public static void f() {
System.out.println("f()");
}
}
class B extends A {
// *must* be public
public static void f() {
System.out.println("Access somewhat denied");
}
}
So I created a trivial test; IntelliJ indeed rejected it... and Yes, I know "it's a tool...but one I trust". In any case, I went to javac, which emitted the same ERROR:
Error:(...) java: ...Concrete.java:5: doSomethingStatic() in
...Concrete cannot override doSomethingStatic() in
...Base; attempting to assign weaker access privileges; was public
Based on this, and our skepticism in general, I suggest the error is in your documentation.
Below is my sample code, fairly definitive I think. It barfs at the protected.
public class Base
{
public static void doSomethingStatic(){}
}
public class Concrete extends Base
{
protected static void doSomethingStatic(){}
}
It can be hidden by an overloaded redeclaration in a derived class:
class Base
{
public static void doSomethingStatic(){}
}
class Derived extends Base
{
public static void doSomethingStatic(String arg){}
}
but only hidden to people who try to access it via the derived class.

override of static method and final method

I know in Java, static method can not be overriden by the subclass.
Two questions:
1. Why is that? Could anyone explain me the reason inside it?
2. Can subclass override final method in super class then?
Static methods aren't called on a particular instance - so they can't be called polymorphically. They are called on the type itself - nothing about the binding relies on any information which is only available at execution time. The point about polymorphic calls is that the method implementation which ends up being executed depends on the execution-time type of the target of the call; there's no target for static method calls, as such.
No, subclasses can't override final methods - the whole point of making a method final is to prevent it from being overridden.

method overriding in Java

How is method overriding implemented in Java? In C++ we have the concept of vtable.. how is this implemented internally in Java?
To answer the question, which is specifically how overriding is implemented in the virtual machine, there's a write up available in Programming for the Java Virtual Machine (Google Books link).
The VM will look for an appropriate method definition in the referenced class, and then work its way up through the inheritance stack. Obviously at some stage various optimisations will apply.
See here for a description of the relevant bytecode instruction invokevirtual:
invokevirtual looks at the descriptor
given in , and determines
how many arguments the method takes
(this may be zero). It pops these
arguments off the operand stack. Next
it pops objectref off the stack.
objectref is a reference to the object
whose method is being called.
invokevirtual retrieves the Java class
for objectref, and searches the list
of methods defined by that class and
then its superclasses, looking for a
method called methodname, whose
descriptor is descriptor.
As gustafc has highlighted below, various optimisations can apply, and no doubt the JIT will introduce further.
Method overriding in Java is a concept based on polymorphism OOPS
concept which allows programmer to create two methods with same name
and method signature on interface and its various implementation and
actual method is called at runtime depending upon type of object at
runtime. Method overriding allows you to write flexible and extensible
code in Java because you can introduce new functionality with minimal
code change.
There are few rules which needs to be followed while overriding any method in Java, failure to follow these rules result in compile time error in Java.
First and most important rule regarding method overriding in Java is that you can only override method in sub class. You can not override method in same class.
Second important rule of method overriding in Java that name and signature of method must be same in Super class and Sub class or in interface and its implementation.
Third rule to override method in Java is that overriding method can not reduce accessibility of overridden method in Java. For example if overridden method is public than overriding method can not be protected, private or package-private; But opposite is true overriding method can increase accessibility of method in Java, i.e. if overridden method is protected than overriding method can be protected or public.
Another worth noting rule of method overriding in Java is that overriding method can not throw checked Exception which is higher in hierarchy than overridden method. Which means if overridden method throws IOException than overriding method can not throw java.lang.Exception in its throws clause because java.lang.Exception comes higher than IOException in Exception hierarchy. This rule doesn't apply to RuntimeException in Java, which is not even need to be declared in throws clause in Java.
You can not override private, static and final method in Java. private and static method are bonded during compile time using static binding in Java and doesn't resolve during runtime. overriding final method in Java is compile time error. Though private and static method can be hidden if you declare another method with same and signature in sub class.
Overridden method is called using dynamic binding in Java at runtime based upon type of Object.
If you are extending abstract class or implementing interface than you need to override all abstract method unless your class is not abstract. abstract method can only be used by using method overriding.
Always use #Override annotation while overriding method in Java. Though this is not rule but its one of the best Java coding practice to follow. From Java 6 you can use #Override annotation on method inherited from interface as well.
--Defining the same method with the same method signature(i.e. same number/type of arguments and same return type/s.)in base and derived class.
--Which method is to be called is decided at runtime so, it is also called runtime polymorphism/late binding.
--we should override the method defined in the superclass.
--when the method is called the method defined in the subclass is called and executed instead of the one in superclass.
--we overcome this by use of 'super' keyword.
//program
class A
{
void disp(){
System.out.println("class A");
}
}
class B extends A
{
public void disp(){
System.out.println("class B");
}
}
public class ExampleIdea{
public static void main(String[] args){
A a = new B(); //Parent reference but B class object (we can achieve polymorphism when parent class reference is used to refer a child class object)
B b = new B(); //B class reference and B class object
A c = new A();
a.disp(); //runs the method in B class
b.disp(); //runs the method in B class
c.disp(); //runs then method in A class
}
}//end of program
when we run this output will be class B.
In order to access the function of class A we have to use super keyword
as:
class B extends A
{
public void disp(){
System.out.println("class B");
super.disp();
}
Maybe this comparison of C++ Vtables and Java method invocation tables is of interest.
Method overriding
It means one method is available in supper class which is displaying some string, but you want to extend this class, and also you want to print your own method at that time you need to overriding this method into your local class.
This is a basic introduction to the method overriding.
Example:
class Animal
{
public void displayMessage()
{
System.out.println("Animal is eating");
}
}
class Dog extends Animal
{
public void displayMessage()
{
System.out.println("Dog is eating");
}
public static void main(String arg[])
{
Dog d=new Dog();
d.displayMessage();
}
}
OUTPUT:
Dog is eating
Advantages of Method Overriding is that the class ca give its own specific implementation to an inherited method without any modifying the parent class method.
The rules of Method overriding are:
The argument list : the argument list must be the same.
Access Modifier : if you're overriding the method you must give the same modifier of super class method suppose super class have the public method you cannot give the protected or private vice versa.
As long as the function (method) you wish to override is not marked as final you just simply override the method by extending the class which holds that method and then provide a method with same signature but different body.

Categories

Resources