static final variable initialization in java - java

I have a doubt in static final variable.In the following program:
class StaticPuzzel2 {
public static void main (String[] args) {
}
final static int i;
static {
System.out.print ("\n\t"+ StaticPuzzel2.i);
i = 11;
System.out.print ("\n\t"+ StaticPuzzel2.i);
System.out.print ("\n\t"+ i);
}
}
Even though the final variable has not been initialized it is not throwing error. Why it is so?

I assume you're wondering why it doesn't throw an error when you access it before setting it to 11. The reason is, that the variable is actually initialized with the default value (zero), and changed at runtime just like any other variable.
When using a static initialization block, the final modifier only makes sure you are assigning a value to the variable only once. What it doesn't do, is making it non-existent before that has happened.

Because it has been already initialized in static block. If you comment out that line it will give a compilation error.

You are initializing static variable in static block. That's why.
Try this:
final static int i = 0;
From java specs :
A variable can be declared final. A final variable may only be assigned to once. It is a compile-time error if a final variable is assigned to unless it is definitely unassigned immediately prior to the assignment
So it doesn't actually means that if should be initialized at declaration. But it means that it can only be assigned once and this assignment can be part of declaration or initializer blocks as in your case.
This is will give you error now.
You can check this answer for more details.
Java - Can final variables be initialized in static initialization block?

Related

final variable initialized first

I was reading the question here : Java : in what order are static final fields initialized?
According to the answer
"except that final class variables and fields of interfaces whose
values are compile-time constants are initialized first ..."
I think this is not correct because the following will fail :
static {
String y = x;
}
public static final String x = "test";
In the static block, x is not recognized. Can anyone please comment if that answer is correct ?
The order of initialization doesn't change the fact that the JLS doesn't let you refer to variables before they're declared in various cases. This is described in JLS§8.3.3:
Use of class variables whose declarations appear textually after the use is sometimes restricted, even though these class variables are in scope (§6.3). Specifically, it is a compile-time error if all of the following are true:
The declaration of a class variable in a class or interface C appears textually after a use of the class variable;
The use is a simple name in either a class variable initializer of C or a static 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.
That's why your code gets this compilation erorr:
error: illegal forward reference
The statement that static fields that are constant variables are initialized first is indeed defined in JLS§12.4.2:
Otherwise, record the fact that initialization of the Class object for C is in progress by the current thread, and release LC.
Then, initialize the static fields of C which are constant variables (§4.12.4, §8.3.2, §9.3.1).
...
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.
As you can see, constant variables are initialized in step 6, but others in step 9.
This demonstrates the behavior:
public class Example {
static String y;
static {
y = foo();
}
static String foo() {
return x.toUpperCase();
}
public static final String x = "test";
public static void main(String[] args) throws Exception {
System.out.println(x);
System.out.println(y);
}
}
That compiles, and outputs:
test
TEST
In contast, if you change the x line so it's not constant anymore:
public static final String x = Math.random() < 0.5 ? "test" : "ing";
It compiles, but then fails because x is null as of y = foo();.
For the avoidance of doubt: I don't recommend using methods to initialize fields like that. :-)
As this answer states:
... they are initialized in the order in which they appear in the source.
You are absolutely right, your example fails, because you are trying to use a variable that is declared after the usage. Since static block are executed in order of the source code, you are absolutely correct and should suggest and edit for that answer, because this statement is invalid:
except that final class variables ... are initialized first.

Un-initialized final local variable vs un-initialized final instance variable [duplicate]

This question already has answers here:
Why Final variable doesn't require initialization in main method in java?
(4 answers)
Closed 4 years ago.
As per my knowledge, final variables must/can be initialized only once otherwise compiler is supposed to throw an error.
If the final instance variable x is not initialized an error is thrown but I faced no error when the local variable y is kept uninitialized in the following code:
import java.util.*;
public class test
{
final int x = 5;// if final variable x uninitialized, compilation error occurs
public static void main(String[] args)
{
final int y; // y is not initialized, **no error is thrown**
System.out.println("test program");
}
}
The local variable isn't used and therefore can be left uninitialized
You will get compile error when try to use it (even if it's not final):
System.out.println("test program" + y);
The local variable y may not have been initialized
The Java Language Specification does not state that a final variable must be assigned (emphasis mine):
A final variable may only be assigned to once.
And:
A blank final is a final variable whose declaration lacks an initializer.
So your y variable is a blank final, and since it's not referenced anywhere further in your code, it's perfectly fine to leave it unassigned.
import java.util.*;
public class test
{
final int x = 5;
public static void main(String[] args)
{
final int y;
System.out.println("test program");
y=6;
y=7;
}
}
y=7 will give error:The final local variable y may already have been assigned. Since it is a final variable, and it has been assigned to 6.
IMHO, a final local variable means once assigned, it cannot be re-assigned. But by final int y you are only declaring a final variable without assignment(initialization), which is legal in Java.(But in order to use it you still have to initialize it, or an error occurs.)
Update:
As commented below, you have noticed the difference between a class field final variable and a local final variable.
From Java Language Specification:
a final field must be definely assigned in the static initializer or the constructor:
8.3.1.2 final Fields
A field can be declared final (§4.12.4). Both class and instance variables (static
and non-static fields) may be declared final.
A blank final class variable must be definitely assigned by a static initializer of
the class in which it is declared, or a compile-time error occurs (§8.7, §16.8).
A blank final instance variable must be definitely assigned at the end of every
constructor of the class in which it is declared, or a compile-time error occurs (§8.8,
§16.9).
(Note that a non-final field can be left un-initialized)
2.A local variable(whether final or not) must be explicitly given a value before it is used:(chapter 4.12.5,P88)
• A local variable (§14.4, §14.14) must be explicitly given a value before it is
used, by either initialization (§14.4) or assignment (§15.26), in a way that can be
verified using the rules for definite assignment (§16 (Definite Assignment)).
As per the definition of a final variable, they can be initialized only once. In your code, you haven't initialized 'y' and you're not using it anywhere as well.
But if you do the following,
final int y;
System.out.println(y);
you will get 'variable y might not have been initialized'
You will get an error when you try to use the declared final variable.
System.out.println(y);

Why can I re-assign a new value to a final variable in Android AIDE?

How this is possible? How am I able to change variables marked as final?
public class Main
{
public static void main(String[] args)
{
final int NUM;
NUM = 22;
NUM = 33;
System.out.println(NUM);
}
}
I was using AIDE app in Android... it compiled successfully and printed 33.
If you can do this, it is a bug in the AIDE app. You should report it to the developers. A JLS compliant implementation of Java does not allow reassignment of final variables (like this).
If you want to give them a JLS specification reference to support your bug report:
JLS 4.12.4 final variables
A variable can be declared final. A final variable may only be assigned to once. It is a compile-time error if a final variable is assigned to unless it is definitely unassigned immediately prior to the assignment (§16 (Definite Assignment)).

Java Compile Time error for instance level Final variables and not giving for method level local variables [duplicate]

This question already has answers here:
Why Final variable doesn't require initialization in main method in java?
(4 answers)
Closed 5 years ago.
Why is the java compiler not giving any compile time error for method level local final variables when we not initialize them?
( but it is giving en error for instance level final variables when they are not initialized ).
public class FinalKeyword
{
final int j; // error: the blank final field j may not have been initialized.
public static void main(String[] args)
{
final int k; // not giving any Compile time error!
}
}
Thing is: as soon as you change your main() method to
final int k;//Not Giving any Compile time error
System.out.println(k); //different story now!
You get an error about k not being initialized, too!
The point is:
the compiler has to make sure that other source code that isn't visible right now ... is able to do a new FinalKeyword() without problems. Thus it can't allow you to keep j not initialized.
but that main() method ... even when another method invokes this main() method - that is fine. The method does nothing! In other words - it is not a problem to define a variable that doesn't get used within a method! Because there is no way how you could get to that variable!
The compiler has to prevent you from getting into situations where you "stumble" over an uninitialized variable. When you invoke a method that has such variables ... but never uses them - that is simply a "don't care".
And surprise: when we go with
public class FinalTest {
public static void main(String args[]) {
final int k;
}
}
and compile that; and then we use javap to get to de-compiled byte code:
public static void main(java.lang.String[]);
Code:
0: return
This is one of the rare occasions where javac does a bit of optimization - by simply throwing away unused variables. Bonus fun fact: even when changing my example to k=5; - you will find that the class file still only contains return!
j is a field of the class. k is not. You need to initialise final fields in the class's constructor. Your class is using your default, implicit constructor which does no initialisation of fields.
The reason it doesn't give you a warning for the local variable is because you don't use it. If you were to use the uninitialised local variable, you would get an error:
public static void main(String[] args)
{
final int k;
if (k < 5) {
// whatever
}
}
As to why the compiler's not clever enough to know that you're not using the field either, I'm not sure. It's presumably more complex because of inheritance, access levels and such.
In general, if the compiler comes across a situation where a final may be accessed while uninitialized, or set while initialized, there is an error.
A class's final fields must be initialized, because someone could access them at any time. If it is package-private, protected, or public, other code can directly access the field, and they expect it to be initialized. Even if the field is private, someone could reflect it and try to access it, so the compiler must not ignore it.
A method's final locals are internal to the method, and there is no way to reflect inside a method without modifying some bytecode, so the compiler does not need to be so strict. Instead, the compiler does control flow analysis to map out when the field will be assigned and won't be assigned, and it will throw an error if it is used while maybe unassigned, and will be content if it is never used or is used while definitely assigned.
void meth0() {
final String s;
// Compiler: s is never used; I don't care.
}
void meth1() {
final String s;
// s is definitely unassigned
if(something()) {
s = "something";
// s is definitely assigned
System.out.println(s);
} else {
// s is definitely unassigned
s = "other";
// s is definitely assigned
System.out.println(s);
}
// if-branch def. assigns s, else-branch def. assigns s
// Ergo: s is def. assigned
somethingElse(s);
// Compiler: control flow checks out; code is valid
}
void meth2() {
final String s;
// def. unass.
if(something()) {
s = "something";
// def ass.
}
// s is in undetermined state
// s = ""; // s may be assigned; error
// use(s); // s may not be assigned; error
// s is now totally unusable. Nice job breaking it, hero!
}

static variable vs non static variable

I have defined an object and declared a static variable i. In the get() method, when I try to print the instance and class variable, both print the same value.
Isn't this.i an instance variable? Should it print 0 instead of 50?
public class test {
static int i = 50;
void get(){
System.out.println("Value of i = " + this.i);
System.out.println("Value of static i = " + test.i);
}
public static void main(String[] args){
new test().get();
}
}
No, there's only one variable - you haven't declared any instance variables.
Unfortunately, Java lets you access static members as if you were accessing it via a reference of the relevant type. It's a design flaw IMO, and some IDEs (e.g. Eclipse) allow you to flag it as a warning or an error - but it's part of the language. Your code is effectively:
System.out.println("Value of i = " + test.i);
System.out.println("Value of static i = " + test.i);
If you do go via an expression of the relevant type, it doesn't even check the value - for example:
test ignored = null;
System.out.println(ignored.i); // Still works! No exception
Any side effects are still evaluated though. For example:
// This will still call the constructor, even though the result is ignored.
System.out.println(new test().i);
The field i is declared as static. You can access static fields either with the YourClass.StaticField or instance.StaticField. So both of
this.i
test.i
are referring to the same value in the context of an instance method of your test class.
It's considered bad practice to access a static field with this.i or instance.i.
static is a class level variable and non static is an instance variable(object level variable) . So here you declare only static variable and call them different way but same meaning.
this.i
test.i
both treated as class level variable or static variable.
you didn't declare any instance variable in here.only one static variable.if you declare instance variable without assigning value,then if you try to print that instance variable value using "this" key word you can get default value as 0.

Categories

Resources