When I call a.displayName("Test")
,it calls the method of class Icecream. displayName(String...s)
method takes in variable arguments.
Output-
test Icecream
test Faloodeh
test Faloodeh: Faloodeh
test Faloodeh: Faloodeh
But when I change the method to displayName(String s)
(I have commented out that section in the code), then it calls the method of class Faloodeh.
New output-
test Faloodeh
test Faloodeh
test Faloodeh: Faloodeh
test Faloodeh: Faloodeh
I wanted to know why does that happen.
class Icecream{
public void displayName(String...s){
System.out.println(s[0]+" "+"Icecream");
}
/*public void displayName(String s){
System.out.println(s+" "+"Icecream");
}
*/
public void describe(String s) {
System.out.println(s+" "+"Icecream: Ice cream");
}
}
class Faloodeh extends Icecream {
public void displayName (String s){
System.out.println(s+" "+"Faloodeh ");
}
public void describe (String s) {
System.out.println(s+" "+"Faloodeh: Faloodeh");
}
}
class Test {
public static void main(String arg[]) {
Icecream a=new Faloodeh ();
Faloodeh b=( Faloodeh)a;
a.displayName("test");
b.displayName("test");
a.describe("test");
b.describe("test");
}
}
**Edit- ** Thanks for the answers. Please help me with another doubt. I changed the code to -
class Icecream{
public void displayName(String s){
System.out.println(s+" "+"Icecream");
}
/*public void displayName(String s){
System.out.println(s+" "+"Icecream");
}
*/
public void describe(String s) {
System.out.println(s+" "+"Icecream: Ice cream");
}
}
class Faloodeh extends Icecream {
public void displayName (String...s){
System.out.println(s+" "+"Faloodeh ");
}
public void describe (String s) {
System.out.println(s+" "+"Faloodeh: Faloodeh");
}
}
class Test {
public static void main(String arg[]) {
Icecream a=new Faloodeh ();
Faloodeh b=( Faloodeh)a;
a.displayName("test");
b.displayName("test");
a.describe("test");
b.describe("test");
}
}
Now this gives the following output-
test Icecream
test Icecream
test Faloodeh: Faloodeh
test Faloodeh: Faloodeh
As you all explained, here b is an object of class Faloodeh. And displayName(String...s)
of class Faloodeh doesn't gets override.
Still in the output, it displays test Icecream
Why so?
The key point here is that changing displayName(String... s)
to displayName(String s)
causes the displayName(String s)
method in Faloodeh
to override the method in its superclass.
Icecream.displayName(String... s)
and Faloodeh.displayName(String s)
have different signatures, so they do not override each other. But changing the former to accept one String
only causes them to have the same signature, which causes overriding to occur.
In Java, method calls are resolved in roughly three steps (for more info: JLS §15.12, I also explained in more detail here):
- Find the class to search for applicable methods. This is based on the compile time type of the object on which you are calling the method. In this case,
a
.a
's compile time type isIcecream
, so onlyIcecream
's methods will be considered. Notice that it doesn't find thedisplayName
method inFaloodeh
because the compile time type ofa
isIcecream
. - Determine which overload of the method to call based on the arguments you passed. There is only one choice here. As both before and after the change,
displayName
is the only overload that is compatible with the arguments you passed. - Determine which implementation of the method to call based on the runtime type of the object on which you called the method.
a
's runtime type isFaloodeh
. Before the change,displayName
is not overridden inFaloodeh
, so it calls the superclass implementation. After the change,displayName
becomes overridden, so the implementation inFaloodeh
is called.
Regarding your edit:
In this case, since the compile time type of b
is Faloodeh
, the class to search is Faloodeh
(Step 1). However, there are 2 methods that matches the arguments you gave (Step 2):
displayName(String...)
which is declared inFaloodeh
, and;displayName(String)
which is inherited.
In such a situation, the compiler always favours the overload without variable arity - displayName(String)
. This is specified clearly in JLS §15.12.2. In particular, Step 2 is further split into three more sub-steps. The first sub-step tries to find a method without allowing variable arity methods, and if any sub-step finds any method, the remaining sub-steps are skipped.