Preface
In Java, an object must be correctly initialized before it can be used, which is stipulated by the Java specification.
Automatic initialization (default)
All basic data members of a class will be initialized. Run the following example to view these default values:
class Default{ boolean t; char c; byte b; short s; int i; long l; float f; double d; public void show() { System.out.println("Basic type initialization value/n"+ "boolean<----->" + t +"/n" + "char<------>" + c +"/n" + "byte<------->" + b + "/n" + "short<------>" + s + "/n" + "int<------>" + i + "/n" + "long<------>" + l + "/n" + "float<------>" + f + "/n" + "double<----->" + d + "/n" ); }}public class InitValue { public static void main(String[] args) { Default d = new Default(); d.show(); }}【Operation results】:
Basic type initialization value
boolean<----->false
char<----->
byte<----->0
short<----->0
int<----->0
long<----->0
float<----->0.0
double<----->0.0
Where, the default value of the char type is null.
For non-primitive data types, the handle of the object is also initialized:
class Person { private String name; // setter}class Default { Person p; public void show() { System.out.println("Person<---->" + p); }}public class InitValue { public static void main(String[] args) { Default d = new Default(); d.show(); }}【Operation results】:
Person<----->null
It can be seen that the handle initialization value is null. This means that if a method similar to p.setName is called without specifying an initialization value for p, an exception will occur.
Regulations initialization
If you need to assign an initial value to a variable yourself, you can assign a value while defining the variable.
class Default{ boolean t = true; char c = 'A'; byte b = 47; short s = 0xff; int i = 24; long l = 999; float f = 1.2f; double d = 1.732; public void show() { System.out.println( "boolean<----->" + t +"/n" + "char<------>" + c +"/n" + "byte<------>" + b + "/n" + "short<------>" + s + "/n" + "int<------>" + i + "/n" + "long<----->" + l + "/n" + "float<------>" + f + "/n" + "double<------>" + d + "/n" ); }}public class InitValue { public static void main(String[] args) { Default d = new Default(); d.show(); }}It can even be initialized in one way;
class Person { int i = set(); //...}These methods can also use independent variables:
class Person { int i; int j = set(i); //...} Builder initialization
The advantage of initializing a builder is that the initialization value can be determined during the runtime. For example:
class Person { int age; Person() { age = 89; }}age will first be initialized to 0 and then become 89. This is true for all basic types as well as handles to objects.
Initialization order
In a class, the order of initialization is determined by the order in which variables are defined within the class. Even if the variable definitions are largely spread across the middle of the method definition, the variable will still be initialized before calling any method (including the constructor). For example:
class Pet { Pet(int age) { System.out.println("Pet(" + age + ")"); }}class Person { Pet t1 = new Pet(1); Person() { System.out.println("---Person()---"); t3 = new Pet(33); } Pet t2 = new Pet(2); void show() { System.out.println("show-----running"); } Pet t3 = new Pet(3);}public class OrderOfInitialization { public static void main(String[] args) { Person p = new Person(); p.show(); }}【Operation results】:
Pet(1)
Pet(2)
Pet(3)
--Person()---
Pet(33)<br/>
show-----running
In the above example, although the definitions of t1, t2, and t3 are all over the class, the order of initialization is determined by the definition order of t1, t2, and t3 (change t1, t2, and t3 by yourself to see the result), and the initialization takes precedence over the builder execution. When the Person builder is called, t3 is re-initialized.
Initialization of static data
If the data is static, the same process will be performed. If it is a primitive type and is not initialized, it will automatically obtain its own standard primitive type initial value; if it is a handle to an object, it will obtain a null value unless an object is created and connected to it. If initialized at definition time, the method taken is different from the non-static value, because static only has one storage area. For example:
class Bowl { Bowl(int marker) { System.out.println("Bowl(" + marker + ")"); } void f(int marker) { System.out.println("f(" + marker + ")"); }}class Table { static Bowl b1 = new Bowl(1); Table() { System.out.println("Table()"); b2.f(1); } void f2(int marker) { System.out.println("f2(" + marker + ")"); } static Bowl b2 = new Bowl(2);}class Cupboard { Bowl b3 = new Bowl(3); static Bowl b4 = new Bowl(4); Cupboard() { System.out.println("Cupboard()"); b4.f(2); } void f3 (int marker) { System.out.println("f3(" + marker + ")"); } static Bowl b5 = new Bowl(5);}public class StaticInitialization { public static void main(String[] args) { System.out.println("Creating new Cupboard() in main"); new Cupboard(); System.out.println("Creating new Cupboard() in main"); new Cupboard(); t2.f2(1); t3.f3(1); } static Table t2 = new Table(); static Cupboard t3 = new Cupboard();}【Operation results】:
Bowl(1)
Bowl(2)
Table()
f(1)
Bowl(4)
Bowl(5)
Bowl(3)
Cupboard()
f(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f(2)
f2(1)
f3(1)
Static code blocks
Java allows other static initialization work to be divided into a special code block in the class. This code block is in the form of a static keyword followed by a method body, called a static code block. A static code block is executed only when the object of that class is generated for the first time or the static member belonging to that class is accessed for the first time. For example:
class Person { Person(int age) { System.out.println("Person(" + age + ")"); } void f(int age) { System.out.println("f(" + age + ")"); }}class Persons { static Person p1; static Person p2; static { p1 = new Person(1); p2 = new Person(2); } Persons() { System.out.println("Persons()"); }}public class ExplicitStatic { public static void main(String[] args) { System.out.println("Inside main()"); Persons.p1.f(18);//1 } static Persons x = new Persons();//2 static Persons y = new Persons();//2}When accessing static object p1 in a line marked 1, or if line 1 is commented and line 2 is not commented, the static initialization module for Persons will run. If both 1 and 2 are commented out, the static code block used for Persons will not be executed.
The order of static properties and static code block execution
class Person { Person(int age) { System.out.println("Person("+age+")"); }}class Persons { static Person p = new Person(2); // 1 static { p = new Person(3); } static Person p = new Person(2); // 2}public class CompStaticInit { public static void main(String[] args) { } static Persons x = new Persons();}According to the analysis of the results of Annotation 1 retaining 2 and Annotation 2 retaining 1, it can be seen that the order of execution of static properties and static code blocks depends on the order of encoding. Whoever is ahead will be executed first.
Initialization of non-static properties
class Animal { Animal(int age) { System.out.println("Animal(" + age + ")"); } void f(int age) { System.out.println("f(" + age + ")"); }}public class NotStaticInit { Animal a1; Animal a2; { a1 = new Animal(1); a2 = new Animal(2); System.out.println("a1 & a2 initialized"); } NotStaticInit() { System.out.println("NotStaticInit"); } public static void main(String[] args) { System.out.println("Inside main()"); NotStaticInit x = new NotStaticInit(); }}Similar to static code blocks, the initialization order of anonymous code blocks with non-static properties depends on the encoding order .
Inherited object initialization process
class Insect { int i = 1; int j; Insect() { prt("i = " + i + ", j = " + j); j = 2; } static int x1 = prt("static Insect.x1 initialized"); static int prt(String s) { System.out.println(s); return 3; }}public class Beetle extends Insect { int k = prt("Beeklt.k initialized"); Beetle() { prt("k = " + k); prt("j = " + j); } static int x2 = prt("static Bootle.x2 initialized"); static int prt(String s) { System.out.println(s); return 4; } public static void main(String[] args) { prt("Beetle constructor"); Beetle b = new Beetle(); }}【Operation results】:
static Insect.x1 initialized
static Bootle.x2 initialized
Beetle constructor
i = 1, j = 0
Beeklt.k initialized
k = 4
j = 2
The first thing that happens when running Java on Beetle is the loader to find that class outside. During the loading process, the loader discovers a basic class, so it is loaded accordingly. This process will be performed regardless of whether the object of the underlying class is generated or not. If the base class contains another base class, the other base class will be loaded, and so on. Next, perform static initialization in the root base class, then execute in the next derivative class, and so on. This is because the initialization of the derivative class may depend on the initialization of the underlying class members.
When all classes are loaded, objects can be created. First, all basic data types in this object are set to their default values and the object handle is set to null. Then execute the builder of the base class. This situation is done automatically ( super(), and the builder of the base class can also be specified through super). After the base class builder is completed, the derived class instance variables will be initialized in their original order, and the remaining body parts of the builder will be executed.
Summarize the process of object creation:
Static execution is only performed when the class is loaded and only once;
Non-static only executes when instantiated, and executes every time an object is created;
Static execution is performed before non-static, and base class static precedes static execution over derivative classes;
The execution properties of static properties and static code blocks depend on their position in the class, and who executes them first;
The execution order of non-static properties and constructor blocks depends on their position in the class and who executes before them.
Summarize
Through the above introduction, we have an understanding of several ways to initialize objects in Java and how to execute the initialization code, and also introduces the situations we may use uninitialized variables. After gaining a detailed understanding of these issues, you can avoid some risks in encoding to ensure that an object is completely initialized before it becomes visible.