我试图了解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)
重要的部分是表达式的编译时类型rs和new 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)).
同样,执行时间类型ss是Square,它不会覆盖add(Rectangle),因此使用实现Rectangle.
让我知道这里的任何事情是否令人困惑 - 如果你可以具体说明哪个部分,这将是伟大的.