Java – 在默认构造函数之前执行的方法

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

 public class ChkCons {int var = getVal();  ChkCons(){System.out.println(“我是默认构造函数。”);  public int getVal(){System.out.println(“我在方法中。”); 返回10;  public static void main(String [] args){ChkCons c = new ChkCons();  }} 

输出:

我在方法。
我是默认构造函数。

谁能解释一下为什么会这样?

谢谢。

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

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

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

 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()方法之前调用。

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

初始化实例成员

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

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

{//初始化需要的代码在这里}

> Java编译器将初始化程序块复制到每个构造函数中。 因此,该方法可用于在多个构造函数之间共享代码块。

无法在子类中重写最终方法。 这在接口和inheritance的课程中讨论。 以下是使用final方法初始化实例变量的示例:

 class Whatever { private varType myVar = initializeInstanceVariable(); protected final varType initializeInstanceVariable() { // initialization code goes here } } 

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

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

参考: 在构造函数代码在Java中运行之前是否初始化了字段?

 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(); 

你应该使用静态方法。

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