Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java overloading method selection

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

  • Method signature gets determined based on compile time data types
  • Actual method invoked depends on the dynamic type of the object the method is called on.

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.

like image 610
Robin Bruegger Avatar asked Feb 03 '13 19:02

Robin Bruegger


People also ask

What are the three ways of method overloading in Java?

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.

What are the different ways a method can be overloaded?

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.

Can overloaded methods have different return types Java?

No, you cannot overload a method based on different return type but same argument type and number in java.


2 Answers

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.

like image 198
Jon Skeet Avatar answered Sep 22 '22 07:09

Jon Skeet


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.

like image 40
JB Nizet Avatar answered Sep 22 '22 07:09

JB Nizet