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具有第一优先级,它在加载类时执行。