Why is this code valid? Appointment before announcement?

This is Java. I understand that the assignment from 1 to index is in the initialization block , which starts when the class is instantiated, but why is this really so?

 public class arr { { index = 1; } int index; void go() { System.out.println(++index); } public static void main(String [] args){ new arr().go(); } } 

The output is 2.

I should get a compilation error symbol not found . Is this behavior native to initialization blocks? In a normal scenario, int index; should appear before index = 1; .

+4
source share
7 answers

+1, it looks weird. But essentially, non-static initialization blocks are simply inserted by javac into object constructors. If we decompile arr.class, we get the real code as

 public class arr { int index; public arr() { index = 1; } void go() { System.out.println(++index); } public static void main(String args[]) { (new arr()).go(); } } 

to get more involved in this puzzle

 public class A { int index; A() { index = 2; } { index = 1; } } 

what's new A (). index ?. The correct answer is 2. See Decompiled A.class

 class A { int index; A() { index = 1; index = 2; } } 

that is, non-static initialization blocks are included in object constructors

+5
source

Non-static initialization blocks start immediately after the constructor, so the code is correct, and the output is as expected.

+4
source

It doesn't matter what order the code is in. As you declare

In the standard index, int int; index = 1 must be reached;

This is exactly what happens when the field is declared and then assigned the value 1. The compiler does not care about the physical ordering of these elements in the class.

+4
source

From the Java Tutorial , the Java compiler copies initialization blocks to each constructor. Therefore, this approach can be used to share a block of code between multiple constructors.

Here is an example of using the final method to initialize an instance variable:

  class Whatever { private varType myVar = initializeInstanceVariable(); protected final varType initializeInstanceVariable() { // initialization code goes here } } 
+2
source

The Java tutorial reads:

A class can have any number of static initialization blocks, and they can appear anywhere in the class body.

Furthermore, this is the same with variables that you can β€œuse” before declaring them:

 class T { public static void main(String[] args) { T t = new T(); System.out.println(ta); } public int a = 14; } 
+1
source

Unlike some languages ​​(such as C), the order in which class variables (static) and instance variables are declared is not related to Java. You can refer to a class / instance variable (in the text) before its declaration. So even that is really ...

 public class X { private int a = b; private int b = a; ... } 

... although initializers actually do not achieve anything useful.

+1
source

Java is a language that fully analyzes your code before doing any trick with it (I try to avoid the boring details of the compiler). Therefore, it does not matter if your initializer block precedes the field declaration, there is a specific order in which everything happens. Class loading (and, of course, field loading), static initializers, constructors, non-static initializers are executed before any method is called (static calls can be executed without executing constructors and non-static elements). You should consider reading some SCJP books (now OCPJP), such as "K and B", to really know what is happening under the hood. A tutorial such as "JVM internals" may be redundant at this point (but you should consider it in your archive for later reference).

0
source

All Articles