Java - 在Default Constructor之前执行的方法

时间:2015-09-21 06:27:45

标签: java constructor

我正在学习java而且我偶然遇到了以下代码,其中默认构造函数在方法之后执行。

public class ChkCons {

    int var = getVal();

    ChkCons() {
        System.out.println("I'm Default Constructor.");
    }

    public int getVal() {
        System.out.println("I'm in Method.");
        return 10;
    }

    public static void main(String[] args) {

        ChkCons c = new ChkCons();

    }

}

输出:

I'm in Method.
I'm Default Constructor.

任何人都可以解释一下为什么会这样吗?

感谢。

6 个答案:

答案 0 :(得分:37)

在执行超类构造函数之后但在执行当前类构造函数体之前,会计算诸如int var = getVal();之类的实例变量初始化表达式。

因此在执行getVal()构造函数的主体之前调用ChkCons

答案 1 :(得分:5)

在方法之前调用构造函数。方法的执行发生在之后,它是对象创建的一部分,其中评估实例变量。从以下代码中可以更好地理解这一点。

class SuperClass{
    SuperClass(){
        System.out.println("Super constructor");
    }
}
public class ChkCons extends SuperClass{

    int var = getVal();

    ChkCons() {
        System.out.println("I'm Default Constructor.");
    }

    public int getVal() {
        System.out.println("I'm in Method.");
        return 10;
    }

    public static void main(String[] args) {

        ChkCons c = new ChkCons();

    }

}

上面的代码有以下输出

Super constructor
I'm in Method.
I'm Default Constructor.

这里编译器自动添加super();作为ChkCons()构造函数中的第一个语句,因此它在getVal()方法之前被调用。

答案 2 :(得分:2)

我们可以参考以下oracle文档初始化实例变量(Emphasis is mine):

  

初始化实例成员

     

通常,您可以使用代码初始化a中的实例变量   构造函数。 使用构造函数有两种选择   初始化实例变量:初始化程序块和最终方法。

     

实例变量的初始化程序块看起来就像静态   初始化程序块,但没有static关键字:

     

{       //无论初始化需要什么代码都在这里}

     

<强>&GT; Java编译器将初始化程序块复制到每个构造函数中。   因此,这种方法可用于共享一段代码   多个构造函数。

     

无法在子类中重写最终方法。这是讨论的   在接口和继承的课程中。这是一个例子   使用最终方法初始化实例变量:

class Whatever {
private varType myVar = initializeInstanceVariable();

protected final varType initializeInstanceVariable() {

    // initialization code goes here
} 
}

https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html

答案 3 :(得分:1)

每当你创建一个类实例的实例时,首先初始化变量,然后执行构造函数

参考:Are fields initialized before constructor code is run in Java?

答案 4 :(得分:1)

public class InitializerIndex {

    public InitializerIndex() {
        // TODO Auto-generated constructor stub
        System.out.println("Default Constructor");
    }

    static {

        System.out.println("Static Block one");
    }

    {
        System.out.println("Init one");
    }

    void letsRoll() {

    }

    public static void main(String[] args) {
        new InitializerIndex().letsRoll();
        new InitializerIndex().letsRoll();
    }

    {
        System.out.println("Init Two");
    }

    static {
        System.out.println("Static Block two");
    }

}

将有以下输出:

Static Block one
Static Block two
Init one
Init Two
Default Constructor
Init one
Init Two
Default Constructor

首先加载所有静态内容,然后加载实例内容。静态内容只加载一次。

即使创建了两个对象,只有在创建第一个对象时才会调用静态块

此外,在创建对象时或在构造函数中,如果要使用此类方法

 int var = getVal();

你应该使用静态方法。

答案 5 :(得分:0)

这是因为您正在使用int var = getVal();将方法初始化为字段,因此它将在构造函数调用之前执行。 静态bloack具有第一优先级,它在加载类时执行。