After some time spent using Java, I always designed my class by following this order: declaring variables, constructor and then methods. And I never thought about this, until I came across code that compiles just fine:
public class Main {
int m1(){
return ++i;
}
int i=10;
}
My question is how does it work? Meaning when compiler starts compiling this code, it should start from top to bottom, right? So how does it know what variable i
stand for and what its value is? "It can't look into the future", to say it the dumb way.
Can someone tell me how does this even work? My only guess is that compiler first compiles variables and then constructor/methods (no matter my order of source code). But I haven't come across any reference/doc to this, so don't want to make blind assumptions.
This works because compilation is done in multiple steps.
One of the first steps is parsing. When the compiler parses the example code, it "notes" that there is a usage of an identifier i
and there is a declaration of a variable that happens to have the name i
. Based on this information (and a set of rules) the compiler matches identifier declarations and identifier usages (and constructs a symbol table, for example).
Checking if the identifier has a correct type for the usage is called type checking and is done in a later step.
So, by the time the compiler "asks" questions like "What does indentifier i
stand for?", it already has the answer from the parsing step.
To determine the value of a variable may be impossible until the run time (for example, if the value is entered by a user). But if the value can be determined at compile time then it can be used for optimization, such as constant propagation, which is one of the later steps in the compilation process.