Why aren't final variables default initialized? Shouldn't the default constructor initialize them to default values if you are happy with the constant be the default value.
Why must you initialized them in the constructor at all? Why can you can't you just initialize them before using them like other variables?
ex.
public class Untitled {
public final int zero;
public static void main(String[] args)
{
final int a; // this works
a = 4; // this works, but using a field doesn't
new Untitled();
}
}
Untitled.java:2: variable a might not have been initialized
Why must you initialize static final variables when they are declared? Why can't you just initialize them before using them in any other method?
ex.
public class Untitled
{
public final static int zero;
public static void main(String[] args)
{
zero = 0;
}
}
Untitled.java:8: cannot assign a value to final variable zero
I'm asking these question because I'm trying to find a logical/conceptual reason why this won't work, why it isn't allowed. Not just because it isn't.
The idea behind a final variable is that it is set once and only once.
For instance final variables, that means they can only be set during initialization, whether at declaration, in a constructor, or an instance initialization block. For the variable to be set anywhere else, that would have to take place in a non-constructor method, which could be called multiple times - that's why this is off limits.
Similarly for static final variables, they can only be set at declaration or in a static initialization block. Anywhere else would, again, have to be in a method which could be called more that once:
public static void main(String[] args)
{
zero = 0;
main(null);
}
As for your first question, I'm assuming it's an error not to explicitly set a final variable in order to avoid mistakes by the programmer.
The Java Language Specification section 8.3.1.2 spells out the rules for final member variables:
A field can be declared final (§4.12.4). Both class and instance variables (static and non-static fields) may be declared final.
It is a compile-time error if a blank final (§4.12.4) class variable is not definitely assigned (§16.8) by a static initializer (§8.7) of the class in which it is declared.
A blank final instance variable must be definitely assigned (§16.9) at the end of every constructor (§8.8) of the class in which it is declared; otherwise a compile-time error occurs.
The JLS doesn't give reasons why the rules are they way they are. However, it might have come from experience in writing Java code, and the above rules are a way to avoid some common coding errors.
The concept of being final means that the variable value cannot change. If you could do as in your second example, then this variable would have been like any other one (i.e. not final)
I don't ave a good rational regarding your first question.
Because, when looking at your code, the Java compiler has no idea whether a given statement will be executed before an other statement. The only exceptions to this rule are code in constructors and implicit constructors, and that's why they're the only place that final fields can be assigned to.
Related
I write java code like this:
final int value=0;
When I use "Svace Static Analyzer" to anylyze the code,it shows:
This class contains an instance final field that is initalized to a compile-time static value, Consider making the field static---->
static final int value=0;
I know static value is loaded in compile time. Can anyone explain the advantage of compile load?
Scenario 1:
class Mango{
final int marker = 10;
}
In a class, when you declare a variable as final and initialize it during declaration, that means you do not want to modify it from anywhere.
In that case, all of the created objects of the class maintained a similar value for this variable.
On the other hand, whenever we declare a variable as static, then at the class level a single variable is created which is shared with the objects. Any change in that static variable reflects to the other objects operations.
But actually, at points 1 and 2 we want to achieve point 3's behavior implicitly.
So, java force or suggest you create only one copy of the marker variable by declaring is static also.
class Mango{
final static int marker = 10;
}
Which is memory efficient, cleaner, and non-ambiguous.
Scenario 2:
public class Mango {
final int marker;
Mango(int m){
marker = m;
}
}
This type of declaration is totally different. In that case, every instance of the Mango class has its own marker variable, and it can be initialized only one time.
The first type of declaration ensures class-level final behavior and the second type of declaration ensures the object-level final behavior.
new to the community, and new to the whole programming world.
While I was studying java, I stumbled on a simple question.
In a main method (or any method), I can declare and initialize a primitive variable on different line just fine. Say,
public static void main (Strin[]args){
int age;
age = 42;
}
will complile just fine.
But if I tried this outside a method, as a class variable or instance variable,
public class test {
int age;
age = 42;
}
the code won't compile. It will only work if the variable is declared and initialized in one line. I was wondering why java doesn't allow this outside a method.
A class body can contain variable declarations and method declarations, but no single statements. When would you expect such a statement to be executed? So your initialization has to be either inline with the declaration (as a shortcut) or in some method, e.g. in the constructor, if you want to initialize the variable when creating a new object.
It is a syntax error! Your code does not comply with the Java syntactic and semantics rules as described in Java Language Specification.
You have to initialise it's value inside the constructor (that's the whole point of a constructor), like
public test() {
age = 42;
}
For static variables it's possible to give them a value:
static int age = 42;
Or use a static block:
static {
age = 43;
}
Like other variables, i want to assign final field type variable to blank but initialization is blocking by Java. What is the its logic? Maybe i want to use default values of my variables? for int = 0, string = null boolean = false etc...
public class Hello {
static final int myNumber; /* it is giving "The blank final field myNumber
may not have been initialized" error in Eclipse */
}
In Java, after you use the final keyword with a static variable, you must define the value at the point of declaration. You must give it some value and stick with it.
A final variable can only be initialized once, either via an initializer or an assignment statement. It does not need to be initialized at the point of declaration: this is called a "blank final" variable.
change your code
public class Hello {
final int myNumber;
public Hello(int num){
this.myNumber = num;
}
}
for static final variable use static block for initialization
static{
myNumber = 0;
}
From the Java specs : "It is a compile-time error if a blank final (§4.12.4) class variable is not definitely assigned (§16.8) by a static initializer (§8.7) of the class in which it is declared."
When you use the "final" modifier with a variable, you must initialize it then as it is the only time you're allowed to use the assignment operator(you can initialize once if you left it blank) on it ("="). Like parker.sikand said, you will get an error if you try to assign a value to it afterwards.
Also, an important note that final STRICTLY means that you cannot use the assignment operator. If the object that is "final" is a mutable object then of course the contents of that object can change without ever using the assignment operator.
EDIT: I believe a final variable has to be guaranteed to be initialized at SOME point in the program which is why you generally initialize it on declaration
Eclipse 2019-09 now proposes a quickfix for that:
Initialize 'final' fields
A Java quickfix is now offered to initialize an uninitialized final field in the class constructor.
The fix will initialize a String to the empty string, a numeric base type to 0, and for class fields it initializes them using their default constructor if available or null if no default constructor exists.
public class Main {
static final int alex=getc();
static final int alex1=Integer.parseInt("10");
static final int alex2=getc();
public static int getc(){
return alex1;
}
public static void main(String[] args) {
final Main m = new Main();
System.out.println(alex+" "+alex1 +" "+alex2);
}
}
Can someone tell me why this prints: 0 10 10? I understand that it's a static final variable and its value shouldn't change but it`s a little difficult to understand how the compiler initializes the fields.
It's an ordering problem. Static fields are initialized in the order that they are encountered, so when you call getc() to inititalize the alex variable, alex1 hasn't been set yet. You need to put initialization of alex1 first, then you'll get the expected result.
This situation is covered by JLS 8.3.2.3 "Restrictions on the use of Fields during Initialization".
The JLS rules allows the usage in your Question, and state that the first call to getc() will return default (uninitialized) value of alex.
However, the rules disallow some uses of uninitialized variables; e.g.
int i = j + 1;
int j = i + 1;
is disallowed.
Re some of the other answers. This is not a case where the Java compiler "can't figure it out". The compiler is strictly implementing what the Java Language Specification specifies. (Or to put it another way, a compiler could be written to detect the circularity in your example and call it a compilation error. However, if it did this, it would be rejecting valid Java programs, and therefore wouldn't be a conformant Java compiler.)
In a comment you state this:
... final fields always must be initialized at compile or at runtime before the object creation.
This is not correct.
There are actually two kinds of final fields:
A so-called "constant variable" is indeed evaluated at compile time. (A constant variable is a variable "of primitive type or type String, that is final and initialized with a compile-time constant expression" - see JLS 4.12.4.). Such a field will always have been initialized by the time you access it ... modulo certain complications that are not relevant here.
Other final fields are initialized in the order specified by the JLS, and it is possible to see the field's value before it has been initialized. The restriction on final variables is that they must be initialized once and only once during class initialization (for a static) or during object initialization.
Finally, this stuff is very much "corner case" behavior. A typical well-written class won't need to
access a final field before it has been initialized.
Static final fields whose values are not compile-time constant expressions are initialized in order of declaration. Thus when alex in being initialized, alex1 is not initialized yet, so that getc() returns default values of alex1 (0).
Note that result will be different (10 10 10) in the following case:
static final int alex1 = 10;
In this case alex1 is initialized by a compile-time constant expression, therefore it's initialized from the very beginning.
There is nothing special about static fields, it just that the compiler cannot workout that you are using a method which can access a field before its initialised.
e.g.
public class Main {
private final int a;
public Main() {
System.out.println("Before a=10, a="+getA());
this.a = 10;
System.out.println("After a=10, a="+getA());
}
public int getA() {
return a;
}
public static void main(String... args) {
new Main();
}
}
prints
Before a=10, a=0
After a=10, a=10
Class variables are not necessary to initialize, they are automatically set to their default values. If primitives (like int, short...) it's 0 (zero) for Objects it's null.
Therefore alex1 is set to 0.
Method variables must be initialized, otherwise you will get an compiliation error.
For a better explanation read http://download.oracle.com/javase/tutorial/java/javaOO/classvars.html
What purpose does it serve?
Just read an example in a book where the author has done so.
int numOfGuesses=0;
The automatic assignment to zero only applies to members, not to local variables. If it is a local variable and the = 0 is omitted then that variable has no value, not even zero. Attempting to use the value before it is assigned will result in a compile error. For example this code attempts to use an uninitialized local variable:
public class Program
{
public static void main(String[] args)
{
int numOfGuesses; // local variable
System.out.println(numOfGuesses);
}
}
and produces this compile error:
Program.java:6: variable numOfGuesses might not have been initialized
System.out.println(numOfGuesses);
Whereas this code using a member works and outputs zero:
public class Program
{
int numOfGuesses; // member variable
public void run()
{
System.out.println(numOfGuesses);
}
public static void main(String[] args)
{
new Program().run();
}
}
For members I tend to assign to zero explicilty if my code uses the fact that the initial zalue is zero, and omit the assignment if my code doesn't use the initial value (for example if it the value is assigned in the constructor or elsewhere). The result is the same either way, so it's just a style issue.
It's more explicit; some people like. Note that this applies only to fields -- local variables need to be initialized; there are no defaults.
The Java compilation and runtime differ.
When running the program, all classes are loaded with class loaders and they do the following:
This is done when class is used for the first time. Their execute order is defined by their order in the code.
run static blocks
static{
//do something here
}
initialize static variables
public static int number;
This will be initialized to zero 0;
The next group of initializations done is when creating an object.Their execute order is defined by their order in the code.
run non-static block
{
// do something here
}
initialize non-static(instance) variables
public int instance_number;
And this is when and why there is default initialization!
This is not true for methods because they don't have similar mechanism as classes.
So basically this means that you will have to initialize EXPLICITLY each method variable.enter code here