首先,有两种类型的初始化块:
以下代码应该说明它们的用法以及执行顺序:
public class Test {
static int staticVariable;
int nonStaticVariable;
// Static initialization block:
// Runs once (when the class is initialized)
static {
System.out.println("Static initalization.");
staticVariable = 5;
}
// Instance initialization block:
// Runs each time you instantiate an object
{
System.out.println("Instance initialization.");
nonStaticVariable = 7;
}
public Test() {
System.out.println("Constructor.");
}
public static void main(String[] args) {
new Test();
new Test();
}
}
输出:
Static initalization.
Instance initialization.
Constructor.
Instance initialization.
Constructor.
如果你想要在无论使用哪个构造函数时都运行某些代码,或者想要为匿名类进行一些实例初始化,那么实例初始化块非常有用。
init()
方法(某些更新类的人可能会忘记调用它)。 - pabliscothis
关键字。 this
是当前类对象,在构造函数调用完成后将完全构造对吧? - amarnath harish我想在@aioobe的回答上添加一些内容
执行顺序:
父类的静态初始化块
类的静态初始化块
父类的实例初始化块
父类的构造函数
类的实例初始化块
类的构造函数。
需要注意的几点(第1点是@aioobe的回答的重述):
静态初始化块中的代码将在类加载时执行(是的,这意味着每个类只加载一次),在构造任何实例和调用任何静态方法之前。
实例初始化块实际上由Java编译器复制到类的每个构造函数中。因此,每次执行实例初始化块中的代码恰好在构造函数中的代码之前。
aioobe 给出了很好的答案,我再增加几点。
public class StaticTest extends parent {
static {
System.out.println("inside satic block");
}
StaticTest() {
System.out.println("inside constructor of child");
}
{
System.out.println("inside initialization block");
}
public static void main(String[] args) {
new StaticTest();
new StaticTest();
System.out.println("inside main");
}
}
class parent {
static {
System.out.println("inside parent Static block");
}
{
System.out.println("inside parent initialisation block");
}
parent() {
System.out.println("inside parent constructor");
}
}
这会给出结果。inside parent Static block
inside satic block
inside parent initialisation block
inside parent constructor
inside initialization block
inside constructor of child
inside parent initialisation block
inside parent constructor
inside initialization block
inside constructor of child
inside main
这就像是在说显而易见的事情,但似乎更加清晰。
这里批准的示例代码是正确的,但我不同意它。它没有展示发生了什么,我将向您展示一个好的例子,以了解JVM实际工作原理:
package test;
class A {
A() {
print();
}
void print() {
System.out.println("A");
}
}
class B extends A {
static int staticVariable2 = 123456;
static int staticVariable;
static
{
System.out.println(staticVariable2);
System.out.println("Static Initialization block");
staticVariable = Math.round(3.5f);
}
int instanceVariable;
{
System.out.println("Initialization block");
instanceVariable = Math.round(3.5f);
staticVariable = Math.round(3.5f);
}
B() {
System.out.println("Constructor");
}
public static void main(String[] args) {
A a = new B();
a.print();
System.out.println("main");
}
void print() {
System.out.println(instanceVariable);
}
static void somethingElse() {
System.out.println("Static method");
}
}
<CLASS_NAME>.<STATIC_VARIABLE_NAME>
)。初始化块包含在创建实例时始终执行的代码。它用于声明/初始化类的各种构造函数的公共部分。
初始化构造函数和初始化块的顺序无关紧要,初始化块总是在构造函数之前执行。
如果我们想为类的所有对象执行一次某些代码怎么办?
我们在Java中使用静态块。
public class StaticInitializationBlock {
static int staticVariable;
int instanceVariable;
// Static Initialization Block
static {
System.out.println("Static block");
staticVariable = 5;
}
// Instance Initialization Block
{
instanceVariable = 7;
System.out.println("Instance Block");
System.out.println(staticVariable);
System.out.println(instanceVariable);
staticVariable = 10;
}
public StaticInitializationBlock() {
System.out.println("Constructor");
}
public static void main(String[] args) {
new StaticInitializationBlock();
new StaticInitializationBlock();
}
}
输出:
Static block
Instance Block
5
7
Constructor
Instance Block
10
7
Constructor
class A {
private List<Object> data = new ArrayList<Object>();
}
2) 在构造函数中分配初始值:
class A {
private List<Object> data;
public A() {
data = new ArrayList<Object>();
}
}
这两个假设您不想将“数据”作为构造函数参数传递。
如果将重载构造函数与上面的内部数据混合使用,情况会变得有点棘手。请考虑:
class B {
private List<Object> data;
private String name;
private String userFriendlyName;
public B() {
data = new ArrayList<Object>();
name = "Default name";
userFriendlyName = "Default user friendly name";
}
public B(String name) {
data = new ArrayList<Object>();
this.name = name;
userFriendlyName = name;
}
public B(String name, String userFriendlyName) {
data = new ArrayList<Object>();
this.name = name;
this.userFriendlyName = userFriendlyName;
}
}
class B {
private List<Object> data;
private String name;
private String userFriendlyName;
public B() {
this("Default name", "Default user friendly name");
}
public B(String name) {
this(name, name);
}
public B(String name, String userFriendlyName) {
data = new ArrayList<Object>();
this.name = name;
this.userFriendlyName = userFriendlyName;
}
}
或者
class B {
private List<Object> data;
private String name;
private String userFriendlyName;
public B() {
init("Default name", "Default user friendly name");
}
public B(String name) {
init(name, name);
}
public B(String name, String userFriendlyName) {
init(name, userFriendlyName);
}
private void init(String _name, String _userFriendlyName) {
data = new ArrayList<Object>();
this.name = name;
this.userFriendlyName = userFriendlyName;
}
}
这两者(或多或少)是等价的。
希望这能给你一些关于如何在对象中初始化数据的提示。我不会谈论静态初始化块,因为那可能对你来说有点高级。
编辑:我理解你的问题是“如何初始化我的实例变量”,而不是“初始化器块是如何工作的”,因为初始化器块是一个相对高级的概念,从问题的语气来看,似乎你在问一个更简单的概念。我可能错了。
初始化块在类被初始化并在构造函数被调用之前执行。它们通常放置在大括号内的构造函数上方。在您的类中包含它们并不是必需的。
它们通常用于初始化引用变量。这个页面提供了一个很好的解释。
补充一下@aioobe和@Biman Tripathy的优秀答案。
静态初始化程序是静态上下文中构造函数的等效物,用于设置静态环境。 实例初始化程序最适合匿名内部类。
代码演示 -
abstract class Aircraft {
protected Integer seatCapacity;
{ // Initial block 1, Before Constructor
System.out.println("Executing: Initial Block 1");
}
Aircraft() {
System.out.println("Executing: Aircraft constructor");
}
{ // Initial block 2, After Constructor
System.out.println("Executing: Initial Block 2");
}
}
class SupersonicAircraft extends Aircraft {
{ // Initial block 3, Internalizing a instance variable
seatCapacity = 300;
System.out.println("Executing: Initial Block 3");
}
{ // Initial block 4
System.out.println("Executing: Initial Block 4");
}
SupersonicAircraft() {
System.out.println("Executing: SupersonicAircraft constructor");
}
}
SupersonicAircraft
的实例创建将按以下顺序生成日志
Executing: Initial Block 1
Executing: Initial Block 2
Executing: Aircraft constructor
Executing: Initial Block 3
Executing: Initial Block 4
Executing: SupersonicAircraft constructor
Seat Capacity - 300