In-depth understanding of Java Initialization

Source: Internet
Author: User

From: http://www.linuxdiyf.com/viewarticle.php? Id = 18987

 

We can think that each class has a method named initialize (). This name implies that it must be called before use. Unfortunately, in this case, you have to remember to call this method. Java class library designers can use a special method called constructor to ensure that every object can be initialized. if there is a constructor in the class, Java will automatically call the constructor when the object is just created and the user is too late to obtain it, so that initialization is guaranteed.

I don't know how much the difference between the original author's description and the translator's understanding is. Combined with the entire chapter, I didn't find two key words "" and "". At least the author and the translator did not really explain what the JVM did during initialization, or did not understand the JVM initialization details. Otherwise, the two methods are clearly available, but why do you think there is a "initialize ()" method that actually does not exist?

Where are the "and" methods? These two methods actually exist and you cannot find them. This may make some masters confused. Coupled with some bugs in JDK implementation, if you do not have a deep understanding, it is really hard to understand.

Now there is a strange phenomenon in the scientific system, so a huge system was initially built on the basis of a hypothesis: Suppose 1 is correct, then 2 is derived, and then continue to export 10000000000. Unfortunately, too many people do not care about systems like 2-00000000000, which are based on the assumption that 1 is correct. I will not use the assumption that "we can think like this". I want to prove that "and" "methods actually exist:

Code: Package debug;
Public class mytest {
Static int I = 100/0;
Public static void main (string [] ARGs ){
Ssytem. Out. println ("Hello, world! ");
}
}

Run the following command to check the output of jdk1.5:

Code: Java. Lang. exceptionininitializererror
Caused by: Java. Lang. arithmeticexception:/by zero
At Debug. mytest. (test. Java: 3)
Exception in thread "Main"

Please note that the exception is located in debug. mytest like the exception generated when calling other methods.

Let's take a look:

Code: Package debug;
Public class test {
Test (){
Int I = 100/0;
}
Public static void main (string [] ARGs ){
New Test ();
}
}

Jdk1.5 input:

Exception in thread "Main" Java. Lang. arithmeticexception:/by zero

At Debug. Test. (test. Java: 4)

At Debug. Test. Main (test. Java: 7)

The JVM does not locate the exception in the test () constructor, but in debug. Test ..

When we see these two methods, we will discuss these two "built-in initialization methods" in detail (I do not like to create some non-standard terms, but I do not know how to name them in a standard way ).

The built-in initialization method is a special method specifically used for initialization by JVM internally, rather than a method provided to the programmer for calling. In fact, you cannot even compile the syntax like "<>" in the source program. This shows that initialization is controlled by JVM rather than programmers.

 

Class initialization method:

I didn't know from any point whether Cl is short for class, but this method is indeed used to initialize "class. In other words, it is used to initialize the static context.

During load, JVM calls the built-in method to initialize class members and static initialization blocks. Their order is in the original order of the source file.

We will add a few static statements:

Code: Package debug;
Public class test {
Static int x = 0;
Static string S = "123 ";
Static {
String S1 = "456 ";
If (1 = 1)
Throw new runtimeexception ();
}
Public static void main (string [] ARGs ){
New Test ();
}
}

Then decompile:

Code: javap-C Debug. Test
Compiled from "test. Java"
Public class Debug. Test extends java. Lang. object {
Static int X;
Static java. Lang. String S;
Public Debug. Test ();
Code:
0: aload_0
1: invokespecial #1; // method Java/lang/object. "" :() V
4: Return
Public static void main (Java. Lang. String []);
Code:
0: New #2; // class debug/test
3: DUP
4: invokespecial #3; // method "" :() V
7: Pop
8: Return
Static {};
Code:
0: iconst_0
1: putstatic #4; // field X: I
4: LDC #5; // string 123
6: putstatic #6; // field S: ljava/lang/string;
9: LDC #7; // string 456
11: astore_0
12: New #8; // class Java/lang/runtimeexception
15: DUP
16: invokespecial #9; // method Java/lang/runtimeexception. "" :() V
19: athrow
}

We can see that class initialization is based on the original sequence defined in the source file. First declare

Code: static int X;
Static java. Lang. String S;

Then assign values to int X and string s:

Code: 0: iconst_0
1: putstatic #4; // field X: I
4: LDC #5; // string 123
6: putstatic #6; // field S: ljava/lang/string;

Execute the string S1 = "456" of the initialization block; generate a runtimeexception and throw

Code: 9: LDC #7; // string 456
11: astore_0
12: New #8; // class Java/lang/runtimeexception
15: DUP
16: invokespecial #9; // method Java/lang/runtimeexception. "" :() V
19: athrow

You must understand that the "" method is not only a class initialization method, but also an interface initialization method. This is not the interface

All attributes are inline. Only interface constants directly assigned constant values can be inline. While

[Public static Final] Double D = math. Random () * 100;

Such expressions need to be calculated and initialized by the "" method in the interface.

 

Next let's take a look at the instance Initialization Method ""

"" Is used to initialize an object when it is created. when an object is created in heap, a space is allocated in heap. The "" method is called first. This method includes instance variable assignment (declaration is not included), initialization block, and constructor call. If there are multiple overloaded constructor methods, each constructor will have a corresponding "" method. The constructor always executes instance variable initialization and block initialization before calling the constructor of the parent class. similarly, the instance variables and initialization blocks are executed in the original source file order. The code in the constructor is executed at the end:

Code: Package debug;
Public class test {
Int x = 0;
String S = "123 ";
{
String S1 = "456 ";
// If (1 = 1)
// Throw new runtimeexception ();
}
Public test (){
String Ss = "789 ";
}
Public static void main (string [] ARGs ){
New Test ();
}
}
Result of javap-C Debug. test:
Compiled from "test. Java"
Public class Debug. Test extends java. Lang. object {
Int X;
Java. Lang. String S;
Public Debug. Test ();
Code:
0: aload_0
1: invokespecial #1; // method Java/lang/object. "" :() V
4: aload_0
5: iconst_0
6: putfield #2; // field X: I
9: aload_0
10: LDC #3; // string 123
12: putfield #4; // field S: ljava/lang/string;
15: LDC #5; // string 456
17: astore_1
18: LDC #6; // string 789
20: astore_1
21: Return
Public static void main (Java. Lang. String []);
Code:
0: New #7; // class debug/test
3: DUP
4: invokespecial #8; // method "" :() V
7: Pop
8: Return
}

If one constructor calls another constructor in the same class, the corresponding "" method calls another ", but the instance variables and initialization blocks are ignored, otherwise, they will be executed multiple times.

Code: Package debug;
Public class test {
String S1 = RT ("S1 ");
String S2 = "S2 ";
Public test (){
S1 = "S1 ";
}
Public test (string s ){
This ();
If (1 = 1) throw new Runtime ();
}
String RT (string s ){
Return S;
}
Public static void main (string [] ARGs ){
New Test ("");
}
}

Decompilation result:

Code: Compiled from "test. Java"
Public class Debug. Test extends java. Lang. object {
Java. Lang. String S1;
Java. Lang. String S2;
Public Debug. Test ();
Code:
0: aload_0
1: invokespecial #1; // method Java/lang/object. "" :() V
4: aload_0
5: aload_0
6: LDC #2; // string S1
8: invokevirtual #3; // method RT :( ljava/lang/string;) ljava/lang/string;
11: putfield #4; // field S1: ljava/lang/string;
14: aload_0
15: LDC #5; // string S2
17: putfield #6; // field S2: ljava/lang/string;
20: aload_0
21: LDC #2; // string S1
23: putfield #4; // field S1: ljava/lang/string;
26: Return
Public Debug. Test (Java. Lang. String );
Code:
0: aload_0
1: invokespecial #7; // method "" :() V
4: New #8; // class Java/lang/runtimeexception
7: DUP
8: invokespecial #9; // method Java/lang/runtimeexception. "" :() V
11: athrow
Java. Lang. String RT (Java. Lang. String );
Code:
0: aload_1
1: areturn
Public static void main (Java. Lang. String []);
Code:
0: New #10; // class debug/test
3: DUP
4: LDC #11; // string
6: invokespecial #12; // method "" :( ljava/lang/string;) V
9: Pop
10: Return
}

We can see that test (string s) calls test (); so "" :( ljava/lang/string;) V no longer initializes instance variables and initialization blocks:

Code: Public Debug. Test (Java. Lang. String );
Code:
0: aload_0
1: invokespecial #7; // method "" :() V
4: New #8; // class Java/lang/runtimeexception
7: DUP
8: invokespecial #9; // method Java/lang/runtimeexception. "" :() V
11: athrow

If the two constructor methods are independent of each other, the instance variables and initialization blocks will be called before each constructor is called:

Code: Package debug;
Public class test {
String S1 = RT ("S1 ");
String S2 = "S2 ";
{
String S3 = "S3 ";
}
Public test (){
S1 = "S1 ";
}
Public test (string s ){
If (1 = 1)
Throw new runtimeexception ();
}
String RT (string s ){
Return S;
}
Public static void main (string [] ARGs ){
New Test ("");
}
}

Decompilation result:

Code: Compiled from "test. Java"
Public class Debug. Test extends java. Lang. object {
Java. Lang. String S1;
Java. Lang. String S2;
Public Debug. Test ();
Code:
0: aload_0
1: invokespecial #1; // method Java/lang/object. "" :() V
4: aload_0
5: aload_0
6: LDC #2; // string S1
8: invokevirtual #3; // method RT :( ljava/lang/string;) ljava/lang/string;
11: putfield #4; // field S1: ljava/lang/string;
14: aload_0
15: LDC #5; // string S2
17: putfield #6; // field S2: ljava/lang/string;
20: LDC #7; // string S3
22: astore_1
23: aload_0
24: LDC #2; // string S1
26: putfield #4; // field S1: ljava/lang/string;
29: Return
Public Debug. Test (Java. Lang. String );
Code:
0: aload_0
1: invokespecial #1; // method Java/lang/object. "" :() V
4: aload_0
5: aload_0
6: LDC #2; // string S1
8: invokevirtual #3; // method RT :( ljava/lang/string;) ljava/lang/string;
11: putfield #4; // field S1: ljava/lang/string;
14: aload_0
15: LDC #5; // string S2
17: putfield #6; // field S2: ljava/lang/string;
20: LDC #7; // string S3
22: astore_2
23: New #8; // class Java/lang/runtimeexception
26: DUP
27: invokespecial #9; // method Java/lang/runtimeexception. "" :() V
30: athrow
Java. Lang. String RT (Java. Lang. String );
Code:
0: aload_1
1: areturn
Public static void main (Java. Lang. String []);
Code:
0: New #10; // class debug/test
3: DUP
4: LDC #11; // string
6: invokespecial #12; // method "" :( ljava/lang/string;) V
9: Pop
10: Return
}

After understanding the above knowledge, let's do a small test:

Code: public class Test2 extends test1
{
System. Out. Print ("1 ");
}
Test2 (){
System. Out. Print ("2 ");
}
Static {
System. Out. Print ("3 ");
}
{
System. Out. Print ("4 ");
}
Public static void main (string [] ARGs ){
New Test2 ();
}
}
Class test1 {
Test1 (){
System. Out. Print ("5 ");
}
Static {
System. Out. Print ("6 ");
}
}

Can you see the print order clearly? What will be printed without new Test2?

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.