构造函数链中的对象类型是什么?

时间:2015-06-29 12:18:03

标签: java inheritance constructor

为什么这段代码只返回类C的名称。当我使用它时,它应该返回我正在使用它的构造函数的类名。

class A{
     public A() {
         System.out.println(this.getClass().getName());
     }
}
class B extends A{
    public B() {
        System.out.println(this.getClass().getName());
    }
}
class C extends B{
     public C() {
         System.out.println(this.getClass().getName());
     }
}
class Main{
    public static void main(String[] args){
         new C();
    }
}

3 个答案:

答案 0 :(得分:4)

svn status ../src 返回this.getClass().getName()实例的运行时类型的名称。如果您创建C(this)的实例,它将始终返回“packagename.C”。如果从类new C()的代码或C的超类中的代码调用它,则无关紧要。

答案 1 :(得分:1)

一些相关要点:

1)编译器将自动在任何不包含对超类构造函数的显式调用的构造函数中插入对无参数超类构造函数的调用。 (我鼓励你在编写代码时选择隐式行为的显式行为,但这是一个有争议的风格点)。无论如何,编译器的代码如下:

class A{
    public A() {
        System.out.println(this.getClass().getName());
    }
}

class B extends A{
    public B() {
        super();
        System.out.println(this.getClass().getName());
    }
}

class C extends B{
    public C() {
        super();
        System.out.println(this.getClass().getName());
    }
}

class Main{
    public static void main(String[] args){
        new C();
    }
}

这清楚表明System.out.println被分三次调用。

2)在构造函数中使用this来调用方法通常会导致非常奇怪的行为。例如,请参阅:this。那是因为初始化的工作原理如下:

1)调用C类构造函数。此时,为C类对象分配内存,并且在VM内填充对象元数据,包括其实现的类,接口。所有字段包括继承的字段都会初始化为其默认值

2)调用B类构造函数。在构造函数内部,它引用了类C的对象,但是在C构造函数中初始化的字段都不会被初始化。这将立即调用A类构造函数。

3)运行A类构造函数。初始化此构造函数中设置的字段。构造函数执行方法和初始化并返回,堆栈传递回B构造函数。

4)B构造函数执行其方法并将控制权返回给C构造函数。

5)C构造函数返回。

所以现在我们了解会发生什么:这个链打印C三次。我怀疑你想要写的是:

    class A{
    public A() {
        System.out.println(A.class.getName());
    }
}

class B extends A{
    public B() {
        super();
        System.out.println(B.class.getName());
    }
}

class C extends B{
    public C() {
        super();
        System.out.println(C.class.getName());
    }
}

class Main{
    public static void main(String[] args){
        new C();
    }
}

将打印出A,B,C。

答案 2 :(得分:0)

首先,当调用new Child()时,由于Child类中没有声明的非参数构造函数,因此它将简单地调用调用Parent构造函数的super()。

然后,当执行this.getClass()。getName()时,这里代表一个Child实例,这就是为什么你得到“Child”作为结果。请记住,Object#getClass()返回对象所属的最具体的类。从here了解更多信息。