I have this following code and I need some clarification regarding the overloading concept.
class Overload{
static void print(Object o){
System.out.println("object");
}
static void print(String s){
System.out.println("string");
}
public static void main(String...args){
print("Hello");
}
}
when I execute this, the output is String. Eventhough object is the super class, why does it display string instead of object?
thanks in advance
The rule in this case is:
the more specific signature will apply
String is more specific than Object, that's why print(String) is used. For instance, try with print(null) in your main, you will see find out that such code will not even compile, since the compiler will have no way to distinguish whether null is a String or an Object
Check out Oracle Overloading Tutorial
There is called string print because you pass "Hello" which is String object.
String also extends regular Object but overloading calls also the most upper type.
Currently, this version of overloaded method executes:
static void print(String s){
System.out.println("string");
}
Since you are calling like this:
print("Hello");
Data conversions happen only if and only if correct version of match is not found. And exact match is found for compiler.
First JVM sees for the print(String), if not found it searches for print() with argument of superclass of String. If still not found, then super-class of super-class of String. And this algorithm continues until there is print(Object). Or reporting an error
Because when there is an exact match, during overloaded functions, JVM will not consider generalization. i.e it will look for the best fit to match the argument type. In this case "Hello" is an exact match to String type. Since String fits better in String than in Object. Hence it will not consider
static void print(Object o)
Related
can someone explain me how this is working ? i'm getting c as my output, it's my 3rd day on java . Thanx in advance
class adarsh
{
private void print( ){
System.out.println("a");
}
private void print(String str){
System.out.println("b");
}
private void print(int x){
System.out.println("c");
}
public static void main(String[] args){
adarsh object = new adarsh();
object.print(12);
}
}
Then a class has multiple methods with the same name and different parameter lists, it's called method overloading. print is an overloaded method in your class. When you use it, the method that gets used depends on the number and type of the arguments you use in the call: The best matching method is used. Because you used 12, which is an integer literal, it has the type int, so print(int) was called. If you'd used no argument, print() would have been called. If you'd used print("foo"), print(String) would have been called.
Side note: Please use the Java naming conventions, at least when asking for help (but it's best when not asking for help, too). Your class should be called Adarsh, not adarsh.
See Method overloading in Java. The method having the signature private void print(int x) was picked by the compiler, since you passed print an int.
What you have tried is an example of Method Overloading which allows different methods to have the same name, but different signatures where the signature can differ by the number of input parameters or type of input parameters or both.
In your code, object.print(12) matches the method based on type of argument.
You call the method by passing an int 12 so the method with int as an argument is invoked and it prints c
Use of Overloading
We don’t have to create and remember different names for functions doing the same thing. For example, in your code, if overloading was not supported by Java, you would have to create method names like print1, print2, print3 … etc.. though all methods do the same printing work. Thus improves readability of code.
And one more thing, Please use the Java Naming Conventions
Class names should be nouns, in mixed case with the first letter of each internal word capitalised.
Use whole words and must avoid acronyms and abbreviations.
I am facing an issue in my program and I made it clear with a small code snippet below. Can anyone explain why this is happening?
class ObjectnullTest {
public void printToOut(String string) {
System.out.println("I am null string");
}
public void printToOut(Object object)
System.out.println("I am null object");
}
class Test {
public static void main(String args[]) {
ObjectnullTest a = new ObjectnullTest();
a.printToOut(null);
}
}
This always prints I am null string .
I want to know the reason so that I can modify the code .
It's because In case of method Overloading
The most specific method is choosen at compile time.
As 'java.lang.String' is a more specific type than 'java.lang.Object'. In your case the method which takes 'String' as a parameter is choosen.
Its clearly documented in JLS:
The second step searches the type determined in the previous step for
member methods. This step uses the name of the method and the types of
the argument expressions to locate methods that are both accessible
and applicable, that is, declarations that can be correctly invoked
on the given arguments.
There may be more than one such method, in
which case the most specific one is chosen. The descriptor (signature
plus return type) of the most specific method is one used at run-time
to perform the method dispatch.
I agree with the existing comment about selection of the most specific method. You can force your null to be treated as an Object reference, eliminating use of the String argument method, by casting it:
a.printToOut((Object)null);
please see section 15.12.2.5 of jls that gives detail regarding how it is chosen
The most specific method is choosen at compile time
LINK TO THE JLS 15.12.2.5
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Method Overloading for NULL parameter
In the code below the output is
String
and if I remove the method with the parameter of type String then the output is
Object
I know how overloading of methods acts when the parameter types don't match exactly but I can not understand how null can be treated as an Object and/or a String parameter.
What is the explanation for this?
class C {
static void m1(Object x) {
System.out.print("Object");
}
static void m1(String x) {
System.out.print("String");
}
public static void main(String[] args) {
m1(null);
}
}
It always uses the most specific method according to the Java specs, section 15.12.2.5.
The intro is reasonably specific about it:
If more than one member method is both accessible and applicable to a method invocation, it is necessary to choose one to provide the descriptor for the run-time method dispatch. The Java programming language uses the rule that the most specific method is chosen.
The informal intuition is that one method is more specific than another if any invocation handled by the first method could be passed on to the other one without a compile-time type error.
Generally speaking, and at least for code readability, it's always best to try to be as explicit as possible. You could cast your null into the type that matches the signature you want to call. But that's definitely a questionable practice. It assumes everyone knows this rule and makes the code more difficult to read.
But it's a good academic question, so I +1 your question.
When multiple overloads match a signature, Java picks the most specific method from among them.
The value of null matches both Object and String, but String is a subclass of Object, so String is picked. If you add another overload with a sibling of String in the class hierarchy, you'd get a compile error.\
// DOES NOT COMPILE
class C {
static void m1(Object x) {
System.out.print("Object");
}
static void m1(String x) {
System.out.print("String");
}
static void m1(Integer x) {
System.out.print("Integer");
}
public static void main(String[] args) {
m1(null);
}
}
Here is a link to a post that discusses your code example at some length.
If you need to force the call of a aprticular overloaded method when passing null as parameter, you have to cast it, like this:
m1((String)null);
By doing this, you make sure you're calling the correct overloaded version of the method.
You have to set the type of null to tell Java what function you want to call.
So you do: m1((Object) null); to call the implementation with the Object parameter and you do m1((String) null); to call the other one.
1. As String is also an object the JVM got confused to call which method at runtime.
2. If you want to specify which method to call at runtime, you can do this by explicit casting
eg:
m1((String)null);
Guess you have a class with some c-tors:
public Foo(int i, String s);
public Foo(float fl, String s);
public Foo(String s, Bar b, boolean f);
Now, when you have the following fn:
public Foo doSomething(Object… args)
{
/*… do something before … */
Foo foo = new Foo( ?!? );
/*… do something after … */
return foo;
}
What should one to to call the correct c-tor? Is there a way to translate args back into the ...-form?
No - after all, there could be any references in there, including null references.
You'd have to check the values you've actually been given against the parameter types for the constructor signatures.
I'd regard this as a sign that you probably shouldn't be using varargs in this situation. You could always overload the method with the same signatures as the constructors, and call common helper methods for the before/after parts... or if the time of the constructor call doesn't matter, do it all in a common method, except the construction:
public void doSomething(int i, String s)
{
doSomethingHelper(new Foo(i, s));
}
Apart from inspecting the concrete type of each element in args, casting them down manually, then invoking the proper constructor via reflection, there isn't much you can do. (And that would be ugly like hell...) The compiler needs to bind constructor calls statically, but you only get to know the concrete parameters at runtime.
An alternative would be to provide a constructor with varargs parameter, but this just delegates the problem one level lower. #Jon's suggestion of getting rid of the varargs altogether is better.
You can, of course check the number and type of the arguments and dispatch accordingly. But note my comment above.
Note that Object... is really just syntactic sugar for Object[]. So you have the same options here as you would if your parameter type was Object[].
package org.study.algos;
public class Study {
public static void main(String[] args) {
A a = new A();
a.m1(null);
}
}
class A {
public void m1(String s) {
System.out.println("String");
System.out.println(s);
}
public void m1(Object obj) {
System.out.println("Object");
System.out.println(obj);
}
}
Here, the output is
String
null
Why does the JVM resolve the method to one with a String argument?
Thanks in advance
J
It's a fairly elaborate algorithm, detailed in JLS 15.12. But the part that is relevant here is 15.12.2, which says "the most specific one is chosen." Both the Object and String overloads are "accessible and applicable" (the String is applicable because a null literal is a reference of all types), and the String is more specific.
EDIT: Corrected section, per Syntactic.
These methods are "overloaded", not "ambiguous".
According to the Java Language Specification:
When a method is invoked (§15.12), the
number of actual arguments (and any
explicit type arguments) and the
compile-time types of the arguments
are used, at compile time, to
determine the signature of the method
that will be invoked (§15.12.2).
And §15.12.2 says:
There may be more than one such
method, in which case the most
specific one is chosen.
String is more specific than Object, so while null is compatible with both, the method with the String parameter is chosen (there are much more complex rules that apply when the parameter types are part of a class or interface hierarchy).
null value can be set to reference of any type.
All overloaded methods you have are in one inheritance hierarchy Object <- String, the least general one is being choosen.
But if you had two overloaded methods that are not in the same hierarchy, then you'd get compilation error about ambigous methods.
A String is an Object, an Object is not a String, thus the first overload is more specific than the second. See JLS 15.12.2, as Syntactic mentioned.
I asked a similar question. Jon Skeet wrote a big answer.
The link to my question: Which overload will get selected for null in Java?