Java重载方法选择

Rob*_*ger 14 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(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)"); }
}
Run Code Online (Sandbox Code Playgroud)

我在这里学到的是

  • 方法签名根据编译时数据类型确定
  • 调用的实际方法取决于调用该方法的对象的动态类型.

基于此,前两次调用的结果与预期的一样.但是,我不理解示例3和4的结果.

它似乎在java语言规范中指定,但我不明白.

Jon*_*eet 20

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

好的,让我们分别看看它们.

例3

//Example 3 prints Rectangle:add(Rectangle). Expected Square:add(Square)
rs.add(new Square());
Run Code Online (Sandbox Code Playgroud)

重要的部分是表达式的编译时类型rsnew Square().

rs只声明为Rectangle,所以编译器将查看声明的方法Rectangle及其超类:

public void add(Figure f)
public void add(Rectangle r)
Run Code Online (Sandbox Code Playgroud)

表达式的类型new Square()Square,因此两种方法都适用 - 但第二种方法更具体.

因此编译器将调用引用add(Rectangle)的对象rs.这是编译时的一面.

在执行时,值rs指的是Square- 但Square不覆盖的实例,add(Rectangle)因此选择的方法是以下实现Rectangle:

public void add(Rectangle r){ System.out.println("Rectangle:add(Rectangle)"); }
Run Code Online (Sandbox Code Playgroud)

例4

//Example 4 prints Rectangle:add(Rectangle). Expected Square:add(Figure)
Square ss = new Square();
ss.add(rs);
Run Code Online (Sandbox Code Playgroud)

再次,让我们考虑所涉及的编译时类型... ss是类型Square,并且rs是类型Rectangle(编译时类型,请记住).

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

public void add(Figure f)
public void add(Rectangle r)
public void add(Square s)
Run Code Online (Sandbox Code Playgroud)

由于编译时类型rs只是Rectangle(不是Square),前两种方法适用,但第三种方法不适用.因此,再次,add(Rectangle)在编译时选择(因为它更具体add(Figure)).

同样,执行时间类型ssSquare,它不会覆盖add(Rectangle),因此使用实现Rectangle.

让我知道这里的任何事情是否令人困惑 - 如果你可以具体说明哪个部分,这将是伟大的.