2017-04-23 119 views
1
class Glyph { 
    void draw() { 
     print("Glyph.draw()"); 
    } 

    Glyph() { 
     print("Glyph() before draw()"); 
     draw(); 
     print("Glyph() after draw()"); 
    } 

} 
class RoundGlyph extends Glyph{ 
    private int radius = 1; 
    RoundGlyph(int r){ 
     radius = r; 
     print("RoundGLyph.draw(), radius = " + radius); 
    } 
    void draw(){ 
     print("radius:" + radius); 
    } 
    public static void main(String[] args){ 
     new RoundGlyph(5); 

    } 

} 

//Glyph() before draw() 
radius:0 
Glyph() after draw() 
RoundGLyph.draw(), radius = 5 

上面的代码。java-当我在构造函数中调用方法时会发生什么?

由于draw()不是静态的,所以必须给它一个隐式参数(this)。在这种情况下,在Glyph的构造函数中调用draw(),所以我想知道这个“隐式参数”是什么。 正如我所知道的,当我调用t.f()时,用t类型的T,编译器会将它变成T.f(t)。

结果表明,在我看来,它是一个作为此参数提供的RoundGlyph。但这怎么可能?显然,在调用draw()时不会创建RoundGlyph。

回答

6

您正在构建一个RoundGLyph实例。 RoundGLyph的构造函数调用超类的构造函数 - Glyph - 它调用draw()方法。由于RoundGLyph覆盖Glyphdraw()方法,Glyph构造函数调用RoundGLyphdraw()方法,该方法打印的值为radius

然而,由于它被调用之前完全初始化的RoundGLyph实例(RoundGLyph构造的身体还没有被尚未执行,甚至radius = 1初始化尚未执行),在radius变量仍持有默认值为0。由于Java语言的这种行为,建议不要在构造函数中调用非final方法(因为它们可以被覆盖)。

+0

感谢您的回答。这是否意味着编译器将RoundGlyph作为第一个参数提供给draw()?正如我所知道的,当我调用t.f()时,用t类型的T,编译器会将它变成T.f(t)。 – Lucas

+1

@Lucas,你的例子中的'draw'方法被称为'this',就像实例方法一样。由于它是从'RoundGlyph'构造函数调用的,'this'是指一个正在构建的'RoundGlyph'实例。正如我们所知,该对象是存在的,因为构造函数正在执行,如果该对象不存在,则无法执行该对象。 “在调用draw()时没有创建RoundGlyph”是错误的。实例在构造函数执行之前由'new'创建。 –

0

在这种情况下,正在调用超级构造函数,即正在调用字形构造函数。现在正在发生的棘手的事情是对RoundGlyph中被重写的draw()方法的调用,因此Glyph会调用RoundGlyph中的重写版本,该版本会打印半径变量,但是又一个奇怪的观察结果是打印0因为子构造函数语句直到现在还没有被执行,所以由于它是一个原语,所以打印默认值0。如果它是某个对象,那么null将被打印。希望澄清它。

1

方法将被正常调用。这次由这个指向的对象是不完美的,但是这个指针在那里,所以不会有异常,但是建议不要这样做,因为在一个不完美的对象上调用实例方法是危险的。

相关问题