我正在学习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.
任何人都可以解释一下为什么会这样吗?
感谢。
答案 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具有第一优先级,它在加载类时执行。