Java 静态块与初始化块与继承中的构造函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21504726/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
static block vs initializer block vs constructor in inheritance
提问by oussama.elhadri
i find this example and i want to understand the logic behind it ? how constructors and static blocks and initializer blocks works in inheritance ? in which stage each one is called ?
我找到了这个例子,我想了解它背后的逻辑?构造函数和静态块以及初始化块如何在继承中工作?每个阶段在哪个阶段被调用?
public class Parent {
static {
System.out.println("i am Parent 3");
}
{
System.out.println("i am parent 2");
}
public Parent() {
System.out.println("i am parent 1");
}
}
public class Son extends Parent {
static {System.out.println("i am son 3");}
{System.out.println("i am son 2");}
public Son() {
System.out.println("i am son 1");
}
public static void main(String[] args) {
new Son();
}
}
the output is :
输出是:
i am Parent 3
i am son 3
i am parent 2
i am parent 1
i am son 2
i am son 1
采纳答案by JB Nizet
A static block is called once, when the class is loaded and initialized by the JVM. An instance initializer is executed when an instance of the class is constructed, just like a constructor.
当 JVM 加载和初始化类时,将调用一次静态块。构造类的实例时会执行实例初始化程序,就像构造函数一样。
Static and Instance initializers are described in the Java Language Specification
Java 语言规范中描述了静态和实例初始值设定项
回答by Vivek Vermani
Static block gets executed when the class is loaded into JVM whereas constructor block gets executed when an instance is created.
静态块在类加载到 JVM 时执行,而构造函数块在创建实例时执行。
A static initializer is the equivalent of a constructor in the static context. You will certainly see that more often than an instance initializer.
静态初始化器相当于静态上下文中的构造函数。您肯定会比实例初始化程序更频繁地看到它。
回答by Girish
Static block called when your class is loaded and your class is first loaded by classloader in jvm so first they get executed
静态块在您的类加载时调用,并且您的类首先由 jvm 中的类加载器加载,因此它们首先被执行
then you create object so your parent init block is called then your parent constructor due to constructor chaining in java then derived class init block then derived class constructor
然后你创建对象所以你的父init块被调用然后你的父构造函数由于java中的构造函数链接然后派生类init块然后派生类构造函数
回答by Pshemo
You need to know that
你需要知道
- first instruction in constructor is invoking constructor of its parent class
super(params)
or if you want to use default constructorsuper()
. In case of default constructor you don't have to write it explicitly. - code in initializer block is moved to every constructor right after
super(...)
call - static block is executed when class is initialized which is done after it is fully loaded (with its parent classes) by JVM.
- 构造函数中的第一条指令是调用其父类的构造函数,
super(params)
或者如果您想使用默认构造函数super()
。在默认构造函数的情况下,您不必显式编写它。 - 初始化块中的代码在
super(...)
调用后立即移动到每个构造函数 - 静态块在类初始化时执行,这是在 JVM 完全加载(及其父类)后完成的。
So classes are compiled into classes similar to this.
所以类被编译成与此类似的类。
public class Parent {
static {
System.out.println("Parent static block");
}
public Parent() {
super();
{
System.out.println("Parent initializer block");
}
System.out.println("Parent constructor");
}
}
public class Son extends Parent {
static {
System.out.println("Son static block");
}
public Son() {
super();
{
System.out.println("Son initializer block");
}
System.out.println("Son constructor");
}
public static void main(String[] args) {
new Son();
}
}
To be able to execute main
method from Son
class JVM needs to loadcode of this class (and classes it extends). After class is fully loaded JVM initializeits static content which involves executing static blocks (yes, there can be more then one static blocks in one class). To fully load Son
class JVM needs to know details about its parent class so it will fully load Parent
class before Son
which means it will also execute its static blocks before static blocks in Son
class.
为了能够main
从Son
JVM 类中执行方法,需要加载这个类(以及它扩展的类)的代码。在类完全加载后,JVM初始化其静态内容,这涉及执行静态块(是的,一个类中可以有多个静态块)。要完全加载Son
类,JVM 需要知道有关其父类的详细信息,因此它会在完全加载Parent
类之前Son
,这意味着它还将在Son
类中的静态块之前执行其静态块。
So output will look like:
所以输出看起来像:
Parent static block
Son static block
Parent static block
Son static block
Now in main
method you are invoking Son
class constructor via new Son()
which code looks like
现在在main
方法中你正在调用Son
类构造函数new Son()
,代码看起来像
super();
{
System.out.println("Son initializer block");
}
System.out.println("Son constructor");
Since its super()
refer to Parent
class constructor, which is
由于它super()
引用Parent
类构造函数,即
super();// this will invoke Object constructor since Parent
// doesn't extend anything (which means it extends Object class)
{
System.out.println("Parent initializer block");
}
System.out.println("Parent constructor");
as result you will see
结果你会看到
Parent initializer block
Parent constructor
Parent initializer block
Parent constructor
This handles Parent#constructor()
executed with super()
so next you will see code from Son constructor after super()
which will generate
这个句柄Parent#constructor()
执行,super()
所以接下来你会看到来自 Son 构造函数的代码,之后super()
将生成
Son initializer block
Son constructor
Son initializer block
Son constructor
To see that classes will be loaded even before you use Son
constructor or even main
method you can just print something before using Son
constructor like
要查看甚至在使用Son
构造函数甚至main
方法之前加载类,您可以在使用Son
构造函数之前打印一些内容,例如
System.out.println("ABC // before new Son()");
new Son();
which will result in
这将导致
Parent static block
Son static block
ABC // before new Son()
Parent initializer block
Parent constructor
Son initializer block
Son constructor