Java重载方法选择

Java重载方法选择,java,overloading,Java,Overloading,我试图弄清楚Java是如何选择执行哪个方法的: //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(Squa

我试图弄清楚Java是如何选择执行哪个方法的:

//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)"); }
}
我学到的是

  • 根据编译时数据类型确定方法签名
  • 实际调用的方法取决于调用该方法的对象的动态类型
基于此,前两次调用的结果与预期一致。但是,我不理解示例3和4的结果

这似乎是合同中规定的,但我不明白

但是,我不理解示例3和4的结果

好的,让我们单独来看一下

示例3

//Example 3 prints Rectangle:add(Rectangle). Expected Square:add(Square)
rs.add(new Square());
重要的部分是表达式
rs
newsquare()
的编译时类型

rs
仅声明为
Rectangle
,因此编译器将查看
Rectangle
声明的方法及其超类:

public void add(Figure f)
public void add(Rectangle r)
表达式
new Square()
的类型是
Square
,因此这两种方法都适用,但第二种方法更为具体

因此,编译器将对
rs
引用的对象调用
add(Rectangle)
。编译时方面就是这样

在执行时,
rs
的值引用了
Square
的一个实例,但是
Square
不会覆盖
add(Rectangle)
,因此选择的方法是
Rectangle
中的实现:

public void add(Rectangle r){ System.out.println("Rectangle:add(Rectangle)"); }
示例4

//Example 4 prints Rectangle:add(Rectangle). Expected Square:add(Figure)
Square ss = new Square();
ss.add(rs);

再次,让我们考虑涉及的编译时类型…code>ss类型为

Square
rs
类型为
Rectangle
(请记住,编译时类型)

Square
及其超类声明的方法是:

public void add(Figure f)
public void add(Rectangle r)
public void add(Square s)
由于
rs
的编译时类型仅为
Rectangle
(而非
Square
),因此前两种方法适用,但第三种方法不适用。因此,同样地,
add(矩形)
是在编译时选择的(因为它比
add(图)
更具体)

同样,
ss
的执行时间类型是
Square
,它不覆盖
add(Rectangle)
,因此使用
Rectangle
中的实现

让我知道,如果在这里有什么是混乱的-如果你能具体说明哪一部分,那将是伟大的

rs.add(new Square());
声明的rs类型为矩形。因此,它查看矩形中的一个方法和所有以正方形或与正方形兼容的类型作为参数的超类。最具体的一个是添加(矩形),因为正方形是矩形,而矩形比图形更具体

Square ss = new Square();
ss.add(rs);

在Square和所有超类中查找方法
add(Rectangle)
<代码>矩形。选择添加(矩形),因为
Square.add(Square)
不适用(矩形不是正方形),
Square.add(图)
不太具体。

作为此作业问题的作者,我可以确认提供的答案是正确的。