I'm learning Java and I have a question.
We can overload a method in various ways and the program executes just one. So the program has to determine which function to use.
My question is, who selects the function? Is it java compiler, or JVM?
Another name to Method Overload is "compile-time polymorphism". At compile-time, java knows which method to call by checking the method signatures. So this is called compile-time polymorphism or static or early binding.
There are two types of polymorphisms. Another kind of polymorphism named as "run-time polymorphism". This is achieved by Method Overriding (parent/child relationship in classes). Object is bound with the functionality at run time. Java virtual machine determines the proper method to call at the runtime, not at the compile time.
Method overloading is handled by the java compiler at compile time based on arguments. Here's an example for method overloading:
class Main{
void func(){System.out.println("No Params");}
void func(int a){System.out.println("Has Params");}
}
Here's a link where you can learn more about it in detail: https://www.infoworld.com/article/3268983/java-challengers-1-method-overloading-in-the-jvm.html
Related
Before I ask my question, let me to explain my understanding and opinion.
By only Overriding we can't achieve polymorphism unless there is upcasting. And as it can only seen at runtime people might have named it as Run time ploymorphism. (I have no objection to call polymorphism as Run Time Polymorphism)
I have objection to call method overloading as compile time polymorphism or polymorphism.
I agree that method overloading is static binding (compile time binding), but I can't see polymorphism in that.
According to the javadoc, there is only polymorphism. There is no compile time or run time polymorphism.
According to javadoc in a section called Defining Methods, it explains Overloading of Methods. But there is nothing about compile time polymorphism.
According to me:
If you put polymorphism in to category of Run time polymorphism, you can only see "compile time polymorphism" when you change your JDK version:
If you switch from a higher JDK version higher to a lower one, you will start seeing compilation errors. The same code behaving differently during compilation time, eg: lambda expression, diamond operator, string in switch case, generics etc.
Let me elaborate my opinion, my prediction about how run time polymorphism and compile time polymorphism came to blogs/tutorials:
Conversation1
Developer 1: Hey I read about polymorphism today. If you do coding to interface, you can achieve polymorphism. writing codes not tightly coupling to a class but instead writing it to interface by making loose coupling, calling a superclass method or interface method actually invokes method of subclass depending on instance passed.
Developer 2: Sorry, I didn't get you.
Developer 1: It's simple at run time which object instance you will pass, that instance method will be executed.
Developer 2: Ohh! Run Time. I got it.
Developer 1: Yes same piece of code, but at Run Time passed instances are different.
Developer 2: **Run Time! Okay, I got it.
Conversation2
Developer 2: Hey yesterday I've met Developer1, he was telling about some run-time polymorphism. By overriding methods in a sub-class we can achieve it.
Developer 3: Run time polymorphism by overriding methods? Then what is oveloading? Compile time polymorphism?
Developer 2: How do you say overloading as compile time polymorphism?
Developer 3: Because it is decided at compile time only.
Developer 2: Silent!
Polymorphism and coding to interface best example is java.sql:
java.sql.Connection conn = DriverManager.getConnection(DB_URL,USER,PASS);
java.sql.Statement stmt = conn.createStatement();
java.sql.ResultSet rs = stmt.executeQuery(sql);
The same piece of code behaves differently based on the Driver registered. This means, if we register the Mysql driver, due to polymorphism this code executes methods of mysql instances. I.e. it executes overridden methods. If you register the Oracle driver, it works for Oracle, and so on.
Above we found same code behaving differently.
Now can anyone show me same code behaving differently in compile time. Or in other words show me add(3,4) method bounded to different methods (other signatured methods) during compile time?
According to javadoc,
The Java programming language supports overloading methods, and Java can distinguish between methods with different method signatures.
The method will be executed depending on signature matched. Having same name for methods does not mean there is a polymorphism, because calling methods signature is different:
Queestion1: If you won't change calling method signature will it call different method other than method for which signature has matched? In any condition will it behave differently?
Let's look at Method overloading:
public void add(int a, int b)
{
System.out.println(a+b);
}
public void add(int a, int b, int c)
{
System.out.println(a+b+c);
}
public static void main(String[] args)
{
add(3,4);
add(3,4,5);
}
Question 1: If method overloading is polymorphism, Which piece of code behaving differently in above block of code? Where is polymorphism here?
Question 2: Method invocation add(3,4); on what scenario it shows ploymorphism, unless it is modified to add(3,4,5)?
EDIT
#FutureVisitor since this thread found no answers in favor of method overloading as a type of polymorphism(Even after a month of question being asked), without any justification accepting answer in favor of Method overloading is not a polymorphism, if any answer points problem in my argument of method overloading is not polymorphism will be accepted and supported their views.
In the Java world, polymorphism means polymorphism between classes. I.e. refering possibly multiple child classes with their common parent. In Java, there is no polymorphism between methods.
void add(int a, int b) and void add(int a, int b, int c) are entirely different methods in the Java syntax. It shouldn't be so - for example, in C++, you can cast them to each other -, but it is so in Java.
The key concept to understand here is the method signature. The method signature defines in a language, what identifies the induvidual methods. (For example, beside a void add(int a, int b);, you simply can't declare an int add(int a, int b); method - the return value is not a part of the method signature in Java, thus the compiler would interpret it as a method re-definition.)
People say
overriding is run time polymorphism and
overloading is compile time polymorphism.
Both are wrong.
Only Overriding is not polymorphism. But overriding helps to achieve polymorphism. If there is no upcasting you can't achieve polymorphism.
Overloading is a concept where method-name along with argument signature is used to bind method call to method body and it can be predicted during compile time only. But this is nowhere related to polymorphism. There is NO behavioral change that can be found in the case of method overloading. Either you compile today or compile after one year behavioral change can only be found if you change calling method signature i.e, only if you modify code to say add(3,4); to add(3,4,5); and hence method overloading is not polymorphism.
I have a code that looks like this
function a(Object m) {}
function a(BasicDbObject) {}
function a(TypeA) {}
function a(TypeB) {}
function a(TypeC) {}
.....
function b(Object m) {
// Some function using Java reflection to determine class of Object m
Class X = c(m);
a(X.cast(m));
}
Here is the problem. It always execute a(Object m) rather than a(BasicDbObject m), even it is BasicDbObject.
My end goal is to execute most closest function to the object passed.
What you are trying cannot be done, because Java is statically typed, and the method overload is resolved at compile-time, not run-time.
The only way to resolve the overload at runtime, is for the method call itself to be done with reflection.
Serious non-answer: wrong approach.
You don't use reflection to dynamically determine a type, to then figure which overloaded method to call.
Instead, use polymorphism. Meaning: don't overload, but override.
Rest assured: getting "reflection" working is hard. Getting it correct, and robust and stable is a super challenging, uphill battle.
You basically want to invent your own personal dynamic dispatch implementation. Unless you have super hard pressing reasons to do so, that is a terrible idea. Because chances are that you will get it wrong. Many many times. And even when your code is working, there will be many incidents later on, when unforeseen things happen in production.
As said: don't do this. Don't fight the language, instead use the means that the language offers you to solve such problems: an inheritance tree of classes, and polymorphic methods. Then let the JVM decide which method to invoke. Most likely, the JVM will do a much better job, compared to what you will come up with.
function a(Object m) {}
function a(BasicDbObject) {}
When methods are overloaded, it may not be intuitive to know the method which gets invoked for any set of parameters because, unlike the situation with overridden methods, the method overloading that gets invoked is determined at compile time (i.e. statically) rather than at run time (i.e. dynamically). This behavior is confusing because overriding methods is more common and this sets our expectations for method invocation.
There are some rules for doing method overloading as robustly and as simply as possible. These are all nicely enumerated in Effective Java (J. Bloch, 2nd and 3rd eds.).
Your situation is made complex because:
You have two overloadings with the same number of parameters whose types are not radically different ... and ...
The behavior of the overloadings is apparently dependent on the type of the parameter (if the behavior was identical, then you simply have one overloading forward to the other)
When this situation arises, you should try to correct it by giving the overloadings different names. It should always be possible to do this and doing so often improves the clarity and maintainability of the code.
If this can't be done for any reason, then the best workaround is to replace the overloadings with a method that accepts the most general parameter type and which invokes helper methods based on the most specific type of the passed argument.
So instead of the above, you can get the behavior you want by using...
public Function a(Object m) {
if (m instanceof BasicDbObject) return doDbObject(m);
if (m instanceof OtherDbObject) return doOtherDbObject(m);
return doGenericObject(m);
}
Note that this isn't the code that you would use when Java adopts pattern matching in the language. Note also that the effect of this code is to give your overloadings different names, but the selection of the distinct method is made at run time using instanceof comparisons rather than at compile time by simply using a distinct name.
TLDR; if you are doing method overloading in a circumstance in which the parameter types are not (or may not be) radically different then you are better off not overloading and using distinct method names.
I am asking this question because in Collection I see that Arrays.sort() is overloaded, so I am wondering how someone can say that a static method is overloaded, when static methods are loaded at class loading time, and overloading is performed after class loading time.
My main question is: overloading and overriding are performed after class loading time; that's why they are visible to objects and invisible to static parts. So can static methods be overloaded?
Compile time and class load time are not the same thing. And run time (in the sense that I use the term in the following ...) is something different again.
Overload analysis is performed at compile time, for both static and instance method calls. The same is true for cases where one static method shadows another static method - it is resolved at compile time.
Override dispatching (for instance methods) occurs at run time; i.e. when the method call actually occurs, depending on the actual object that is the "target" object.
why Arrays.sort() is overloaded , when it is static
Why shouldn't it be?
As I said, both static and instance methods can be overloaded. (Overriding is restricted to instance methods, and instance methods only ... but overloading can be used with all kinds of methods, and to constructors too.)
Also "loading" and "overloading" are totally unrelated concepts. "Loading" is about getting classes (in this case) into memory, but "overloading" is about different methods with different signatures that have the same name.
Both static and dynamic polymorphism are part of polymorphism.
In static polymorphism, the overloading is resolved at compile time, in dynamic, it's resolved at runtime. In spite of that both are valid cases of overloading.
This question already has answers here:
What is the main difference between Inheritance and Polymorphism?
(18 answers)
Closed 5 years ago.
Do both inheritance and polymorphism constitute an IS-A relationship? And is it true that inheritance and "overriding" polymorphism happen in runtime while "overloading" polymorphism occurs in compile time? The reason I ask this is because a lot of forums seem to give conflicting and often confusing answers.
Thanks!
For your first part of the question I think Wikipedia provides a good definition:
In object-oriented programming, subtype polymorphism or inclusion
polymorphism is a concept in type theory wherein a name may denote
instances of many different classes as long as they are related by
some common super class. Inclusion polymorphism is generally
supported through subtyping, i.e., objects of different types are
entirely substitutable for objects of another type (their base
type(s)) and thus can be handled via a common interface.
Alternatively, inclusion polymorphism may be achieved through type
coercion, also known as type casting.
Another Wikipedia artile called Polymorphism in object-oriented programming seems to answer your questions very well. The second reference in this article called On Understanding Types, Data Abstraction, and Polymorphism also covers this matters in great detail.
This subtyping feature in Java is achieved, among other means, through inheritance of classes and interfaces. Although the subtyping features of Java may not be evident in terms of inheritance all the time. Take for example the cases of covariance and contravariance with generics. Also, arrays are Serializable and Cloneable although this is not evident anywhere in the type hierarchy. It can also be said that through primitive widening conversion, also numeric types in Java are polymorphic. And operator behave polimorphically depending on their operands.
At any rate, inheritance plays an important role in the implementation of some of this polymorphism.
Overloading vs Overriding
Your second part of the question seems to be about choosing the implementation of a given method. Evidently, if a class overrides a method and you create an instance of that class you want the overriden version of method to be invoked, even if you are accessing the object through a reference of the parent class.
The selection of the right implementation of method is done at runtime as you well pointed out, now the signature of the method to be invoked is decided at compile time. Since overloading is about different methods with the same name and different signature, that is why it is said that overriding method selection happens at compile time.
Overriding Method Selection at Compile Time
The Java Language Specification (JLS) in section 15.12 Method Invocation Expressions explains in detail the process that the compiler follows to choose the right method to invoke.
There, you will notice that this is a compile-time task. The JLS says in subsection 15.12.2:
This step uses the name of the method and the types of the argument expressions
to locate methods that are both accessible and applicable
There may be more than one such method, in which case the most specific one is chosen.
To verify the compile-time nature of this, you can do the following test.
Declare a class like this and compile it.
public class ChooseMethod {
public void doSomething(Number n){
System.out.println("Number");
}
}
Declare a second class that invokes a method of the first one and compile it.
public class MethodChooser {
public static void main(String[] args) {
ChooseMethod m = new ChooseMethod();
m.doSomething(10);
}
}
If you invoke the main, the output says Number.
Now, add a second more specific overloaded method to the ChooseMethod class, and recompile it (but do not recompile the other class).
public void doSomething(Integer i) {
System.out.println("Integer");
}
If you run the main again, the output is still Number.
Basically, because it was decided at compile time. If you recompile the MethodChooser class (the one with the main), and run the program again, the output will be Integer.
As such, if you want to force the selection of one of the overloaded methods, the type of the arguments must correspond with the type of the parameters at compile time, and not only at run time.
Overriding Method Selection at Run time
Again, the signature of the method is decided at compile time, but the actual implementation is decided at runtime.
Declare a class like this and compile it.
public class ChooseMethodA {
public void doSomething(Number n){
System.out.println("Number A");
}
}
Then declare a second extending class and compile:
public class ChooseMethodB extends ChooseMethodA { }
And in the MethodChooser class you do:
public class MethodChooser {
public static void main(String[] args) {
ChooseMethodA m = new ChooseMethodB();
m.doSomething(10);
}
}
And if you run it you get the output Number A, and this is Ok, because the method has not been overriden in ChooseMethodB and therefore the implementation being invoked is that of ChooseMethodA.
Now, add an overriden method in MethodChooserB:
public void doSomething(Number n){
System.out.println("Number B");
}
And recompile just this one, and run the main method again.
Now, you get the output Number B
As such, the implementation was chosen at runtime, and not recompilation of the MethodChooser class was required.
Polymorphism: Ability of different objects to receive same message and respond to differently.
Inheritance a way to achieve it, but not necessary. See Duck Typing
Overloading of a method is 'compile time syntax helper'- as every method gets a unique signature after compilation. Not really anything to do with polymorphism.
Polymorphism is an effect of inheritance. It can only happen in classes that extend one another.
Polymorphism does happen at runtime; I've never heard of "overloading polymorphism".
Inheritance happens at compile time, the moment you write:
class A extends B
{
}
I think you're right.
Polymorphism considers the runtime type of the object to decide wich method execute and the choice of which overloaded method to call is not dinamically decided at runtime, it depends on the types of the parameters at compilation time.
Only inheritance constitute an IS-A relationship. polymorphism has nothing to do with it.
"overloading" is example of polymorphism. You can learn more about run-time and compile-time polymorphism here
• Inheritance defines parent-child relationship between two classes, polymorphism takes advantage of that relationship to add dynamic behavior in your code.
• Inheritance encourages code reusability by allowing child class to inherit behavior from the parent class. On the other hand, Polymorphism allows the child to redefine already defined behavior inside the parent class. Without Polymorphism, it's not possible for a child to execute its own behavior while represented by a Parent reference variable, but with Polymorphism it can be done.
• Java doesn't allow multiple inheritance of classes but allows multiple inheritance of Interface, which is actually required to implement Polymorphism. For example, a class can be Runnable, Comparator and Serializable at the same time because all three are interfaces. This makes them pass around in code e.g. you can pass an instance of this class to a method which accepts Serializable, or to Collections.sort() which accepts a Comparator.
• Both Polymorphism and Inheritance allow Object-oriented programs to evolve. For example, by using Inheritance you can define new user types in an Authentication System and by using Polymorphism you can take advantage of the already written authentication code. Since, Inheritance guarantees minimum base class behavior, a method depending upon super class or super interface can still accept an object of the base class and can authenticate it.
Public class John {
public void setValue(){
this.value = 0;
}
public void setValue(int v){
this.value = v;
}
Now potentially how would i call these two methods??
John j = new John();
j.setValueO();
j.setValue(10);
Correct me if i am wrong.
Is function overloading a concept of polymorphism? If not, under which OOP branch does this come.
Encapsulation means Hiding the information and Abstraction means Hiding the implantation details. So when i do overload a method, do i carry anything on these two above... {Abstraction and Encpsulation}
Is Overloading compile time or runtime? Why do they call this for overloading and overriding?
Yes you are right, expect the typo which you have made?
Is function overloading a concept of polymorphism? If not, under
which OOP branch does this come.
Well speaking from historical point of view, it does come but still many argue that its not a form of polymorphism.
Overloading
The method functions differently based on the arguements.
Overriding
The method functions differently based on which class was used to instainate it.The method bark could sound differently for Class CAT and Class DOG.
Encapsulation means Hiding the information and Abstraction means
Hiding the implantation details. So when i do overload a method, do i
carry anything on these two above... {Abstraction and Encpsulation}
Nope. May be someone can answer on this much clearer.
Is Overloading compile time or runtime? Why do they call this for
overloading and overriding?
Compile time. In overriding the decision that method of which class is to be called is decided at runtime, hence it is runtime.
In overloading the method definition, availability based on the parameters passed in the method call is checked at compile time only.
Java does not identify methods by their names alone, but by their signatures. A signature is composed of the method name and the ordered list of parameter types. So, from a compiler and jvm point of view, those are two completely different methods. The fact that they share the name (and as a consequence a similar signature) has no meaning if not for humans.
Since signatures are used in .class files, the compiler is responsible for computing the signature of a method call, using method name and parameters, at compile time. The late binding that happens at runtime is related to polymorphism, beacuse the current instance on which a certain method is called could be an instance of a subclass that override a certain method, wether that method is also overloaded or not, in java, is not considered by the runtime at all.
You cannot have two method with the same signature in the same class. Notably, the return type of a method is not part of its signature, so you cannot have two method with the same and and same parameters but returning two different types.
In other languages, javascript for example, since parameters are always dynamic, the signature is only composed of the name of the method, which makes overloading impossible
As to the first part of your question, yes the code you showed is an example of overloading, well, assuming the first part is correct and the 0 in the second part is a typo.
I'm not familiar with how these topics are formally taught these days, but to my mind overloading isn't really related to polymorphism. It's just a convenient way for methods that more or less do the same thing (and often call each other) to share a name. I have no idea how to answer your second question. What is an "OOP branch"?
Again, I'm not quite sure how these tie in. Doesn't it depend on what the method actually does?
Well, think about it this way. In Java, when you call a method in general, leaving overloading aside, at what phase does the system figure out which method you're calling (as opposed to which class's implementation of that method)? As to the origin of those terms, honestly that should be pretty easy to look up.
Since function overloading can work very well without objects, I do not see any reason for it to be an OOP concept at all. For the question whether it's polymorphism, it does fulfill the general requirements and according to Wikipedia is a form of polymorphism.
In general, when you create a method you always do both (you abstract away some general functionality and you hide the information of the internal workings of the function). Overloading does not add to neither, IMO. (Even though through overloading and the gained polymorphism you could argue to gain in abstraction, since the function becomes more generic, it is IMO still on the same level of abstraction.)
Overload resolution is - which was suprising to me at first - compile time. This is in contrast to the mentioned overriding. (So its in that sense not the same kind of polymorphism, as one is runtime and the other one is compile time.)