Why method overloading is the best example of static binding in Java? - java

In java, I know that we have some differences between static binding and dynamic binding and method overloading is the best example of static binding but I don't know why it is the method overloading instead of the the method overriding?

Method overloading is determined at compile time. The compiler decides, based on the compile time type of the parameters passed to a method call, which method having the given name should be invoked. Hence the static binding.
Method overriding is determined by the runtime type of an object. At runtime, the method that gets executed can be a method of some sub-class that wasn't even written when the code that makes the call was compiled. Hence the dynamic binding.

Related

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

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

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

why polymorphism doesn't matters when a method is overloaded?

i know that overloaded methods are determined at compile time based on the reference type which invokes the method while overrided methods is determined by the actual object type of the reference invoking he method, the question is why polymorphism only matters about overriding and not overloading?
The implementation mechanism that makes polymorphism in Java possible is the dynamic dispatch of a method based on the runtime type of its first argument (in a call a.method(b, c), a can be considered the first argument of the method). Java is therefore a single dispatch OOP language. The upshot is that all other arguments don't participate in this mechanism and their type is determined statically at compile time. So for example if you have
class MyObject {
public boolean equals(MyObject o) { ... }
}
and then
MyObject m1 = new MyObject();
Object o = new MyObject();
System.out.println(m1.equals(o));
can never print true since your method is not being called. The compiler saw a call MyObject.equals(Object) and compiled it as a call of the inherited method Object.equals(Object). The runtime method dispatch mechanism will only decide which overriding method equals(Object) to call.
polymorphism , as the name implies , is when a method "of the same form" manifests different behaviours under different contexts. The term "same form" means "same signature". That implies you cannot relate polymorphism with overloaded methods because they have "different forms" to begin with. Another way to think about it is - you need a type and a subtype to see polymorphism in action - overloaded methods again are defined in the context of a single class.
This is for technical reasons. Usually only the this pointer, as hidden first parameter of the method, is analyzed at runtime to determine the method to be called.
When other parameters, too, are analyzed it is called Multiple Dispatch. There are a few languages that support multiple dispatch natively.
You are confused on this.
Overloading refers to selecting one of the methods having the same name but different signature in the same class (not hierarchy).
Overriding is chose among methods of the same name depending on the runtime type among those inherited by parent classes.
If you have a base class and a derived class with a method of the same name and signature then this is overriding and at runtime the correct is determined.
For overloading the compiler picks the correct version of method to use, among the available in the same class.
No need to find a runtime type. Compiler can figure this out at compile time

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.

Clarification on overloading

When the parent class have an add method with 2 parameters, If we add new add method with 3 parameters in child class, shall we call this as over loading?
Thanks in advance.
Yes, since the method with two parameters is inherited by the subclass, the method with three parameters is said to be an overloading method.
class A
add(param1, param2)
class B
add(param1, param2) <-- inherited
add(param1, param2, param3) <-- overloading the above method
A quote from the official trail on Overriding and Hiding Methods:
Note: In a subclass, you can overload the methods inherited from the superclass. Such overloaded methods neither hide nor override the superclass methods—they are new methods, unique to the subclass.
(As you probably already figured out, the method with three classes is not an overriding method.)
Yes, this is overloading. It would be overloading even if the method were in the same class as the method with two parameters.
Note that when there are different numbers of parameters (and no varargs parameters) overloading is reasonably simple. It gets a lot more complicated when you have methods with the same number of parameters - at that point the compiler has to choose the "best" method out of applicable candidate methods.
Also note that overloading is determined at compile time whereas which override is executed is determined at execution time based on the actual type of the object the method is called on.
Overloading is when methods have the SAME NAME but DIFFERENT SIGNATURE.
Overriding - when methods have IDENTICAL NAMES and IDENTICAL SIGNATURE.
Yes definitely a overloading and a nice feature of inheritance.
If the method name already exists but the parameters are different, then yes, this is overloading.
yep... it is overloading method even if the method is located in the same class.
ps: i assume the new method with three parameters has identical name and return type

Categories

Resources