Videos
What are the types of access modifiers in Java?
What is static keyword in Java?
A local variable1 is "in scope" if code can access it and out of scope if it can't. In Java, variables are scoped to the block ({}) they're declared in. So:
void foo() {
int a = 42;
if (/*some condition*/) {
String q = "Life, the Universe, and Everything";
// 1. Both `a` and `q` are in scope here
System.out.println(a);
System.out.println(q);
if (/*another condition*/) {
// 2. Both `a` and `q` are in scope here, too
System.out.println(a);
System.out.println(q);
}
}
// 3. Only `a` is in scope here
System.out.println(a);
System.out.println(q); // ERROR, `q` is not in scope
}
Note (1), (2), and (3) above:
The code can access
qbecauseqis declared in the same block as the code; tt can accessabecause it's declared in the containing block.The code can access
qbecause it's declared in the containing block; it can accessabecause it's in the next block out.The code can access
a, but notq, becauseqisn't declared in the block or any of the blocks (or a couple of other things) containing it.
When figuring out what an unqualified identifier (like a or q above, as opposed to the foo in this.foo or the toLowerCase in q.toLowerCase, which are qualified) is, the Java compiler will look in each of these places, one after the other, until it finds a match:
- For a variable with that name in the innermost block
- For a variable with that name in the next block out, and so on
- For a field2 or method (generally: member) with that name in the current class
- For a class with that name from a package that's been imported
- For a package with that name
There are a few others for that list (I'm not going to get into static imports with a beginner).
There's a lot more to scope, I suggest working through some tutorials and/or a beginning Java book for more.
1 "local variable" vs. "variable" - The Java Language Specification uses "variable" in a more general way than most people do in common speech. When I say "variable" in this answer, I mean what the JLS calls a "local variable".
2 "field" - The JLS calls fields "variables" in some places (and "fields" in other places), hence (1) above. :-)
From Section 6.3 of the Java Language Specification:
The scope of a declaration is the region of the program within which the entity declared by the declaration can be referred to using a simple name, provided it is visible.
This concept of scope applies to many kinds of entities in Java: everything from local variables to top-level classes and packages. Even when just talking about variables, there are many cases, from local variables to statically imported fields from another class to the parameter of an exception handler in a catch clause of a try statement. For details, read the JLS or search the web for "Java scope" and read one or more of the many tutorials on the subject that show up.
According to the JLS, Section 12.4.1, initialization of class variables proceeds from top to bottom, in "textual order":
The static initializers and class variable initializers are executed in textual order, and may not refer to class variables declared in the class whose declarations appear textually after the use, even though these class variables are in scope (ยง8.3.2.3). This restriction is designed to detect, at compile time, most circular or otherwise malformed initializations.
So, if you make your own compiler to recognize forward class variable declarations, then it is violating the Java Language Specification.
I will give you a simple piece of code:
public class Test
{
private int foo = bar;
private int bar = foo;
}
What would you expect this to do?
I presume that designers of Java has done it so because assignment of values to instance variables must be executed in some order. In the case of Java, they are executed downwards (from up to bottom).
EDIT
What about this?
public class Test {
private int foo = quu++;
private int bar = quu++;
private int quu = 1;
}
What values would foo and bar have? Which quu++ statement would be executed first?
My point is, Java designers must have thought that it is counter intuitive to do it as you did describe in your question, i.e. unordered execution with compile time code analysis.
FINAL EDIT
Let's complicate things:
class Test {
private James james = new James(anInt);
private Jesse jesse = new Jesse(anInt);
private IntWrapper anInt = new IntWrapper();
}
class James {
public James(IntWrapper anInt) {
if(--anInt.value != 0) {
new Jesse(anInt);
}
else {
anInt.isJames = true;
}
}
}
class Jesse {
public Jesse(IntWrapper anInt) {
if(--anInt.value != 0) {
new James(anInt);
}
else {
anInt.isJames = false;
}
}
}
class IntWrapper {
public int value = 99;
public boolean isJames;
}
I am not sure what it proves regarding your question because I am not sure about your point.
There is no circular dependency here but value of an instance variable of IntWrapper, isJames, depends on the execution order and it might be difficult to detect this kind of stuff with a lexical/semantic analyzer.