Analyzing some weird scenarios in following static block :
static {
System.out.println("Inside Static Block");
i=100; // Compilation Successful , why ?
System.out.println(i); // Compilation error "Cannot reference a field before it is defined"
}
private static int i=100;
While same code is working fine while using :
static {
System.out.println("Inside Static Block");
i=100; // Compilation Successful , why ?
System.out.println(MyClass.i); // Compiles OK
}
private static int i=100;
Not sure why variable initialization do not need variable access using class name while SOP requires ?
This is because of the restrictions on the use of Fields during Initialization. In particular, the use of static fields inside a static initialization block before the line on which they are declared can only be on the left hand side of an expression (i.e. an assignment), unless they are fully qualified (in your case MyClass.i).
So for example: if you insert int j = i; right after i = 100; you would get the same error.
The obvious way to solve the issue is to declare static int i; before the static initialization block.
this is because compilers doing static code analysis, for example the live variable analysis (backward analyze). It calculates for each program point whether the variable will be read before the next write.
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Java static class initialization
in what order are static blocks and static variables in a class executed?
When I run this code the answer is 1, I thought it would be 2.
What is the order of initialization and the value of k in each step?
public class Test {
static {k = 2;}
static int k = 1;
public static void main(String[] args) {
System.out.println(k);
}
}
Edit 1: As a follow up to "k is set to default value" then why this next code doesn't compile? Theres an error "Cannot reference a field before it's defined".
public class Test {
static {System.out.println(k);}
static int k=1;
public static void main(String[] args) {
System.out.println(k);
}
}
Edit 2: For some unknow to me reason it^ works when instead of "k" its "Test.k".
Thanks for all the answers. this will sufice :D
They are executed in the order that you write them. If the code is:
public class Test {
static int k = 1;
static {k = 2;}
public static void main(String[] args) {
System.out.println(k);
}
}
then the output becomes 2.
The order of initialization is: ..the class variable initializers and static initializers of the class..., in textual order, as though they were a single block.
And the values (for your code) are: k = 0 (default), then it's set to 2, then it's set back to 1.
You can check that it's actually set to 2 by running the following code:
private static class Test {
static {
System.out.println(Test.k);
k = 2;
System.out.println(Test.k);
}
static int k = 1;
public static void main(String[] args) {
System.out.println(k);
}
}
Short answer
When the initialization of the class starts, k will have initial value of 0.
The static block (since it precedes the assignment in the declaration) is then executed, and k will be assigned 2.
Then the initializer in the declaration is executed, and k will be assigned 1.
Long explanation
Let us use this example, since your example is a bit simple:
class TestInitOrder {
static {
System.out.println(TestInitOrder.stat1);
System.out.println(TestInitOrder.stat2);
System.out.println(TestInitOrder.str);
System.out.println(TestInitOrder.str2);
str = "something";
System.out.println(TestInitOrder.str);
System.out.println(TestInitOrder.str2);
System.out.println(TestInitOrder.lazy);
System.out.println(TestInitOrder.second);
}
private static final int stat1 = 10;
static final String str2 = "sdfff";
static String str = "crap";
private static int stat2 = 19;
static final Second second = new Second();
static final int lazy;
static {
lazy = 20;
}
static {
System.out.println(TestInitOrder.str2);
System.out.println(TestInitOrder.stat2);
System.out.println(TestInitOrder.str);
System.out.println(TestInitOrder.lazy);
System.out.println(TestInitOrder.second);
}
public static void main(String args[]) {
}
}
class Second {
public Second() {
System.out.println(TestInitOrder.second);
}
}
According to Java Language Specification, from section 4.12.5:
Every variable in a program must have a value before its value is used:
Each class variable, instance variable, or array component is initialized with a default value when it is created
(The following lines from the specification specify the default value for all the types, basically some form of 0, such as 0, 0.0d, null, false, etc.)
So before the class is initialized (due to one of these reasons), the variables will hold an initial value.
According to the detailed initialization procedure (only the interesting steps are quoted here, and emphasis mine):
6.
[...] Then, initialize the final class variables and fields of interfaces whose values are compile-time constant expressions (§8.3.2.1, §9.3.1, §13.4.9, §15.28).
[...]
9.
Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block.
Let us look at step 6, with the 4 final class variables: stat1, str2, second, lazy.
Since 10 is constant expression, and so is "sdfff", and due to the order of execution, it is not possible to observe the initial value for str2 and stat1. In order to make an observation, the earliest you can do is in step 9.
The case of second demonstrate that when the right hand side is not a compile-time constant expression, so its initial value is visible.
The case of lazy is different, since the assignment is done in static block, and hence happen in step 9 - so it is possible to observe its initial value. (Well, the compiler checks carefully that lazy is assigned exactly once).
After the initialization of final class variables with compile-time constant expression comes the execution of static blocks and the rest of the initializers.
As you can see from the example, the static blocks and initialization happens according to textual order - demonstrated with the use of str variable - it is first printed out as null, then something, then crap.
This question already has answers here:
What does a "Cannot find symbol" or "Cannot resolve symbol" error mean?
(18 answers)
Closed 5 years ago.
I am new to exception handling in java.
I was just trying to clear my concepts,but i encountered the following problem.
Here is the code.
class Inn {
public static void main(String... args) {
try{
String i="Asd";
} catch(Exception e) {
System.out.println(e);
}
//i=7;
System.out.println(i);
}
}
And here is the error which is coming.
G:\javap>javac Inn.java
Inn.java:13: error: cannot find symbol
System.out.println(i);
^
symbol: variable i
location: class Inn
1 error
try { // Block A
String i="Asd";
} // End of Block A
catch(Exception e) {
System.out.println(e);
}
System.out.println(i); // 'i' does not exist in this scope
The variable i is declared within the code block A, which means that it could only be accessible from inside of it (notice the { curly braces } that limit its scope). As soon as the execution flow passes by the block A, the variable i will no longer exist in scope.
That being said, if you want to make this work, you gonna have to declare the string i out of the inner scope:
String i = ""; // necessary initialization, without it you'll get a
// "variable may have not been initialized" error
try {
i = "Asd";
}
catch(Exception e) {
System.out.println(e);
}
The i variable is defined in a different scope and is not visible at the point where you are trying to print it.
Rewrite is as:
import java.io.*;
class Inn
{
public static void main(String s[])
{
String i = null;
try{
i="Asd";
}catch(Exception e)
{
System.out.println(e);
}
//i=7;
System.out.println(i);
}
}
That way, variable i is in the same scope as the println statement.
With most programming languages, one generally associates a scope to a variable. What the scope means in layman terms is - the section of code where the variable can be used or where the variable is visible.
With Java (or many OOP languages for that matter) we generally have various levels of scope :
Class Level Scope : Variables defined in the class i.e the member variables can be accessed anywhere within the class (I'm keeping the static modifier out of the picture for the sake of simplicity). These variables are generally defined at the top of the class (convention). Keep in mind that these variables need to be outside the methods of the class to be in the class level scope.
public class Example {
private String a; // variable a can be accessed anywhere inside the class
}
Method Level Scope : Variables defined within a method can be accessed inside the method only. Their lifetime ends when the method returns.
private int giveMeFive(){
int a = 5; // Scope of a is within the method
return a; // When a is returned then there the variable a dies :(
}
Loop Level Scope : Variables you define within the loops are restricted to that loop and any inner loops. They cannot be accessed outside the loop in which they are defined.
public static void main(String []args){
for(int i=0;i<10;i++){
System.out.println(i); // Only i is accessible here but not j
for(int j=1;j<5;j++){
System.out.println(i+j); // Both i and j are accessible here
}
}
}
Block level scope : In general, whatever resides inside of curly brackets { } defines a particular scope. In Java you can usually access a variable as long as it was defined within the same set of brackets or any brackets within these brackets.
In your case you defined the variable i within the try block so as soon as the try block finished the variable was no longer visible and hence could not be found by your println statement later on in the code.
public static void main(String[] args){
String i; // i defined outside the try block so it can be accessed after the try finished running
try{
i= "Asd"
}catch(Exception e){
Sytem.out.println(e);
}
System.out.println(i);
}
All the best :)
It is because the scope of i is juste in try block.
Variable i is defined inside the try block, which restricts the scope of i inside try block. You need to define it outside the try block.
Java is an scoped language, therefore the visivility of a variable depends of where it is defined.
In computer programming, the scope of a name binding – an association of a name to an entity, such as a variable – is the part of a computer program where the binding is valid: where the name can be used to refer to the entity.
Java is lexically scoped.
Problem with "scopes" of variables in try catch blocks in Java
Because your string i was declared in the try block, the println method is not able to find it. (it is out of scope)
Some may find it similar to the SO question Will Java Final variables have default values? but that answer doesn't completely solve this, as that question doesn't directly print the value of x within instance initializer block.
The problem arises when I try to print x directly inside the instance initializer block, while having assigned a value to x before the end of the block :
Case 1
class HelloWorld {
final int x;
{
System.out.println(x);
x = 7;
System.out.println(x);
}
HelloWorld() {
System.out.println("hi");
}
public static void main(String[] args) {
HelloWorld t = new HelloWorld();
}
}
This gives a compile time error stating that variable x might not have been initialized.
$ javac HelloWorld.java
HelloWorld.java:6: error: variable x might not have been initialized
System.out.println(x);
^
1 error
Case 2
Instead of directly printing, I am calling a function to print:
class HelloWorld {
final int x;
{
printX();
x = 7;
printX();
}
HelloWorld() {
System.out.println("hi");
}
void printX() {
System.out.println(x);
}
public static void main(String[] args) {
HelloWorld t = new HelloWorld();
}
}
This compiles correctly and gives output
0
7
hi
What is the conceptual difference between the two cases?
In the JLS, §8.3.3. Forward References During Field Initialization, its stated that there's a compile-time error when:
Use of instance variables whose declarations appear textually after the use is sometimes restricted, even though these instance variables
are in scope. Specifically, it is a compile-time error if all of the
following are true:
The declaration of an instance variable in a class or interface C appears textually after a use of the instance variable;
The use is a simple name in either an instance variable initializer of C or an instance initializer of C;
The use is not on the left hand side of an assignment;
C is the innermost class or interface enclosing the use.
The following rules come with a few examples, of which the closest to yours is this one:
class Z {
static int peek() { return j; }
static int i = peek();
static int j = 1;
}
class Test {
public static void main(String[] args) {
System.out.println(Z.i);
}
}
Accesses [to static or instance variables] by methods are not checked in this way, so the code above produces output 0, because the variable initializer for i uses the class method peek() to access the value of the variable j before j has been initialized by its variable initializer, at which point it still has its default value (§4.12.5 Initial Values of Variables).
So, to summarize, your second example compiles and executes fine, because the compiler does not check if the x variable was already initialized when you invoke printX() and when printX() actually takes place at Runtime, the x variable will be assigned with its default value (0).
Reading the JLS, the answer appears to be in section 16.2.2:
A blank final member field V is definitely assigned (and moreover is not definitely unassigned) before the block (§14.2) that is the body of any method in the scope of V and before the declaration of any class declared within the scope of V.
This means that when a method is called, the final field is assigned to its default value 0 before invoking it, so when you reference it inside the method, it compiles successfully and prints the value 0.
However, when you access the field outside of a method, it is considered unassigned, hence the compilation error. The following code will also not compile:
public class Main {
final int x;
{
method();
System.out.println(x);
x = 7;
}
void method() { }
public static void main(String[] args) { }
}
because:
V is [un]assigned before any other statement S of the block iff V is [un]assigned after the statement immediately preceding S in the block.
Since the final field x is unassigned before the method invocation, it is still unassigned after it.
This note in the JLS is also relevant:
Note that there are no rules that would allow us to conclude that V is definitely unassigned before the block that is the body of any constructor, method, instance initializer, or static initializer declared in C. We can informally conclude that V is not definitely unassigned before the block that is the body of any constructor, method, instance initializer, or static initializer declared in C, but there is no need for such a rule to be stated explicitly.
The difference is that in the first case you are calling System.out.println from initializer block so the block which is invoked before constructor. In the first line
System.out.println(x);
variable x is not yet initialized so that you get compilation error.
But in the second case you call instance method which doesn't know if variable has already been initialized so you don't have compilation error and you can see the default value for x
Ok, here is my 2 cents.
We all know that final variables can be initialized only While declaring or later on in constructors. Keeping that fact in mind, let see what happened here so far.
No errors Case:
So when you use inside a method, it have already a value.
1) If you initialize it, that value.
2) If not, the default value of data type.
Error case :
When you do that in an initialization block, which you are seeing errors.
If you look at the docs of initialization block
{
// whatever code is needed for initialization goes here
}
and
The Java compiler copies initializer blocks into every constructor. Therefore, this approach can be used to share a block of code between multiple constructors.
In compiler's eye, your code is literally equals to
class HelloWorld {
final int x;
HelloWorld() {
System.out.println(x); ------------ ERROR here obviously
x = 7;
System.out.println(x);
System.out.println("hi");
}
public static void main(String[] args) {
HelloWorld t = new HelloWorld();
}
}
You are using it before even initializing it.
Case 1 :
Gives you a compile-error,
Because at System.out.println(x);
you are trying to print x which was never initialized.
Case 2:
Works because you are not directly using any literal values, instead you are calling some method, which is correct.
General Rule is,
If you are trying to access any variable which is never initialized
then it will give a compilation error.
We deal here with initializer block. The Java compiler copies initializer blocks into every constructor.
The compiler error don't occure in second example, because printing x is in another Frame, please refer to spec.
I was reading about the static flow control and came across the RIWO concept. Can someone explain this with simple terminology and perhaps a code sample?
This is related to the error "Illegal forward reference".
Relevant link.
After going through some material and discussing with couple of guys offline i found out the following information.
When a java class is getting executed there are few steps which JVM performs few steps sequentially.
Identify the static members from top to bottom.
Executes static variables assignments and static blocks from top to bottom.
Executes the main method.
During these phases there is one such state called RIWO(Read Indirectly Write Only) for a static variable.
During RIWO a variable cannot be accessed directly with its reference. Instead we need to use an indirect way to call certain variables.
for example:
class Riwo
{
static int i = 10;
static
{
System.out.println(i);
}
}
In the above case the output is 10.
class Riwo {
static int i = 10;
static {
m1();
System.out.println("block1");
}
public static void main(String... args) {
m1();
System.out.println("block main");
}
public static void m1() {
System.out.println(j);
System.out.println("block m1");
}
static int j = 20;
static {
System.out.println("end of code");
}
}
In the above case the output is
0
block m1
block1
end of code
20
block m1
block main
class Riwo
{
static
{
System.out.println(i);
System.out.println("block1");
}
static int i = 10;
public static void main(String... args)
{
System.out.println("main block");
}
}
In the above case we get the following compile time error
Riwo.java:5: illegal forward reference
System.out.println(i);
That means we cannot read a static variable directly when it is in RIWO state.We should call the variable indirectly using a method.
Static variable have two states
RIWO (Read Indirectly Write Only)
RW(Read Write).
RIWO:
Before assigning original value to static variable, variable state is called as RIWO state.
RW:
After assigning original value to static variable, variable state is called as RW state.
Static variable have two type of reading
Direct Read
InDirect Read
Direct Read:
Reading static variable from static block directly is called direct reading.
InDirect Reading:
Reading static variable from static block by calling another method is called indirect reading.
Direct Read Example:
Note: when static variable in RIWO state we cant perform Direct Reading.
class DirectReadingExample{
static {
System.out.println("i==="+i);
}
//i is in RIWO state
static int i=100;
//i is in RW State
}
Output:
compile time Error:illegal forward reference.
InDirect Read Example:
Note: when static variable in RIWO state we can perform InDirect Reading.
class InDirectReadingExample{
static {
m1();
}
static m1(){
System.out.println("i===="+i);
}
//i is in RIWO state
static int i=100;
//i is in RW State
}
Output:
i===0
If a variable is just identified by JVM and the original value is not
yet assigned, then the variable is said to be in the RIWO(Read Indirectly Write Only) state.
The following code is legal:
class Test{
static int num=10;
static
{
System.out.print(num);
System.exit(0);
}
}
output:
10
The code below will produce a compile time error(illegal forward reference)
class Test{
static
{
System.out.print(num);
}
static int num=10;
}
//Produces Compile time error
The code below is legal:
class Test{
static
{
int x=readVar();
}
static int readVar(){
System.out.println(num);
return 0;
}
static int num=10;
static
{
System.out.print(num);
}
}
output:
0
10
In this case, we're not performing a direct read, but rather an indirect
read via a method call. The variable num is identified by JVM - step 1.
Then the default value 0 is assigned to num at that time.
I am getting ready for a java certification exam and I have seen code LIKE this in one of the practice tests:
class Foo {
int x = 1;
public static void main(String [] args) {
int x = 2;
Foo f = new Foo();
f.whatever();
}
{ x += x; } // <-- what's up with this?
void whatever() {
++x;
System.out.println(x);
}
}
My question is ... Is it valid to write code in curly braces outside a method? What are the effects of these (if any)?
Borrowed from here -
Normally, you would put code to initialize an instance variable in a
constructor. There are two alternatives to using a constructor to
initialize instance variables: initializer blocks and final methods.
Initializer blocks for instance variables look just like static
initializer blocks, but without the static keyword:
{
// whatever code is needed for initialization goes here
}
The Java compiler copies initializer blocks into every constructor. Therefore, this approach can be used to share a block of code between multiple constructors.
You may also wanna look at the discussions here.
This is an initializer block that is executed while the instance of the class is being loaded/created and that is used to initialize member properties of a class (See Java http://download.oracle.com/javase/tutorial/java/javaOO/initial.html). You can have as many blocks as you want and they will be instantiated from top to bottom.
In addition to the instance block, you can have as many static blocks as you want as well to initialize static members. They would be declared as follows:
public class Initialization {
static int b = 10;
int a = 5;
static {
b = -9;
}
{
a += 2;
}
public static void main(String[] args) throws Exception {
System.out.println(ClientVoting.b);
System.out.println(new ClientVoting().a);
System.out.println(ClientVoting.b);
System.out.println(new ClientVoting().a);
}
static {
b = 1;
}
{
a++;
}
}
While the class is being initialized, the static member "b" is initialized as 10, then the first static scope changes its value to -9, and later to 1. This is only executed once while the class is loaded. This executes before the initialization of the first line of the main method.
On the other hand, the similar example to your class is the instance reference "a". A is initialized as 5, then the instance block updates it to 7, and the last block to 8. As expected, the static members are only initialized once in this code, while the instance blocks are executed EVERY time you create a new instance.
The output to this example is 1 8 1 8
It's an initializer block. It's used to set instance variables. The motivation to use initializer blocks over constructors is to prevent writing redundant code. The Java compiler copies the contents of the block into each constructor.