Java forward references are prone to errors

Source: Internet
Author: User

Forward references are used before defining classes, interfaces, methods, and variables. For example,

class MyClass  {      void method()      {          System.out.println(myvar);      }      String myvar = "var value";  }  

Myvar is defined after the method, but the method can use this variable first. Many languages, such as C ++, need to be defined in advance, and Java has allowed forward references. However, when using forward references, it may be easy to make some mistakes. For example, the following code.

    class MyClass {           int method() {return n; }           int m = method();           int n = 1;      }  

If you simply execute the following code, it will undoubtedly Output 1.

System.out.println(new MyClass().method()); 

However, the following code outputs the variable M, but returns 0.

System.out.println(new MyClass().m);  

So is that true?

In fact, we can learn from the working principles of the Java compiler and runtime. During Java source code compilation, only lexical, syntax, and semantics are detected. If both are passed, A. Class file is generated. However, the variables in myclass are not initialized. The Compiler only records the corresponding initialization expressions (method () and 1) in the. Class file.

When runtime runs myclass. Class, the member fields are first loaded and executed in order. It does not initialize all the values that can be initialized because JAVA supports forward references. First, runtime will initialize the M field first, then of course the method will be called, and N is used in the method by the forward reference technology. However, N has not been initialized yet. To implement forward reference, runtime also needs to add all fields to the symbol table before initializing all fields. These fields can be referenced anywhere (but must meet the Java call rules). However, because these fields have not been initialized, all fields in the symbol table use the default values. The default value of an int type field is 0. Therefore, when int M = method () is initialized, the N accessed by the method is actually the field n that has been added to the symbol table before formal initialization, instead of the result of int n = 1. However, if you change myclass to the following format, the results are completely different.

    class MyClass {          int method() {return n; }          int n = 1;          int m = method();      }  

Execute the following code and Output 1.

    System.out.println(new MyClass().m);  

The reason is that the method is called when m is initialized. The N used in this method is already initialized, rather than the value originally placed in the symbol table.

Based on the above, Runtime is running. in a class file, each symbolic table with its own scope (methods, interfaces, classes, and other language elements) will be accessed at least twice, for the first time, all fields (only class initialization is considered here) will be placed in the symbol table. Initialization is not considered for the time being. Put in the symbol table is only equivalent to an index, so that you can find these fields when referencing them elsewhere. For example, if n is referenced in the method, n is found in the symbol table, but n is the default value of the int type. When the second access to N is to initialize N (INT n = 1 ). This is to update the value of field N stored in the symbol table to the actual initialization value (1 ). So if the reference N is released before the formal initialization of N, of course, the output is 0.

Someone may ask, first access N and then access M. Is the value of M 1? The answer is still 0. Because the initialization of M and N has been completed when the myclass object is created, their values become a fact. They cannot be changed unless you set them again.

Myclass = new myclass (); system. Out. println (myclass. N); // output 1 system. Out. println (myclass. m); // still output 0

Static members still comply with this rule.

Class myclass {static int method () {return N;} static int M = method (); // directly access M, 0 static int n = 1 ;}

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.