I'm trying to get my head round how Java selects which method is executed:
//Example 1 prints Square:add(Figure)
Figure fs = new Square();
fs.add(fs);
//Example 2 prints Square:add(Figure)
Rectangle rs = new Square();
rs.add(fs);
//Example 3 prints Rectangle:add(Rectangle). Expected Square:add(Square)
rs.add(new Square());
//Example 4 prints Rectangle:add(Rectangle). Expected Square:add(Figure)
Square ss = new Square();
ss.add(rs);
class Figure
{
public void add(Figure f){ System.out.println("Figure:add(Figure)"); }
}
class Rectangle extends Figure
{
@Override
public void add(Figure f){ System.out.println("Rectangle:add(Figure)"); }
public void add(Rectangle r){ System.out.println("Rectangle:add(Rectangle)"); }
}
class Square extends Rectangle
{
@Override
public void add(Figure f){ System.out.println("Square:add(Figure)"); }
public void add(Square s){ System.out.println("Square:add(Square)"); }
}
What I've learned here is
Based on that, the result of the first two calls is as expected. However, I don't understand the result of example 3 and 4.
It seems to be specified in the java language specification, but I don't understand it.
The different ways of method overloading in Java can be achieved by varying parameters list in one of the below way: Number of parameters. The data type of parameters. The sequence of Data type of parameters.
Overloading MethodsBy changing the number of parameters in a method. By changing the order of parameters in a method. By using different data types for parameters.
No, you cannot overload a method based on different return type but same argument type and number in java.
However, I don't understand the result of example 3 and 4.
Okay, let's look at them individually.
Example 3
//Example 3 prints Rectangle:add(Rectangle). Expected Square:add(Square)
rs.add(new Square());
The important parts are the compile-time types of the expressions rs
and new Square()
.
rs
is only declared as Rectangle
, so the compiler will look at the methods declared by Rectangle
and its superclasses:
public void add(Figure f)
public void add(Rectangle r)
The type of the expression new Square()
is Square
, so both methods are applicable - but the second one is more specific.
So the compiler will call add(Rectangle)
on the object that rs
refers to. That's it for the compile-time side.
At execution time, the value of rs
refers to an instance of Square
- but Square
doesn't override add(Rectangle)
so the method picked is the implementation in Rectangle
:
public void add(Rectangle r){ System.out.println("Rectangle:add(Rectangle)"); }
Example 4
//Example 4 prints Rectangle:add(Rectangle). Expected Square:add(Figure)
Square ss = new Square();
ss.add(rs);
Again, let's consider the compile-time types involved... ss
is of type Square
, and rs
is of type Rectangle
(compile-time types, remember).
The methods declared by Square
and its superclasses are:
public void add(Figure f)
public void add(Rectangle r)
public void add(Square s)
As the compile-time type of rs
is only Rectangle
(not Square
), the first two methods are applicable, but the third isn't. Therefore, again, add(Rectangle)
is picked at compile time (as it's more specific than add(Figure)
).
Again, the execution time type of ss
is Square
, which doesn't override add(Rectangle)
, so the implementation in Rectangle
is used.
Let me know if anything in here is confusing - if you can be specific about which part, that would be great.
rs.add(new Square());
The declared type of rs is Rectangle. So it looks at a method in Rectangle and all superclasses taking a Square or a type compatible with Square as argument. The most specific one is add(Rectangle)
since Square is a Rectangle, and since Rectangle is more specific than Figure.
Square ss = new Square();
ss.add(rs);
Looks for a method add(Rectangle)
in Square and all super-classes. Rectangle.add(Rectangle)
is chosen, since Square.add(Square)
doesn't apply (a Rectangle is not a Square), and Square.add(Figure)
is less specific.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With