Why unnecessarily initialize a variable? - java

We know that there is a default of each primitive data type in Java(For e.g.:- The default value of double data type is 0.0d.).Then if we want the value of a variable(suppose double a) to be equal to the default value,why should we need to specify the value as:
double a=0.0d;
Why can't we not just use the default value of the variable anywhere as its default value is the same as the value we want to assign?

Different types do have default values that will be assigned to any unassigned fields of that type. However, this does not apply to local variables, as shown in the Language Specification §4.12.5:
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)).
I speculate that this is to make your code clearer. In a method, you would want readers of your code know what each and every variable's value is, instead of relying on the reader remembering facts like "a booleans default value is false". Since what you are writing is likely an algorithm of some sort, you want to write it as clearly as possible for other people.
In fields however, this is not required. I think this is because you are not describing a set of steps to do something. Instead, you are just saying that this object has some property. The semantics are a little different here.

As per Java language specification local variable must be initilized before use. Let's see why would such rule would have been made for local variables and not for instance variables.
Compiler tries to eliminate as much errors as possible during compile time only thereby making the application runtime more stable. For this it detects the issues it can at compile time and throws compile time exceptions.
Non final instance variables can be initilized in constructor (which may be multiple, overloaded) or in one of the methods of the class. Before using such a variable compiler does not complain as it assumes programmer would have provided the initial value in some method or constructor. The initilization depends on run time of the application as during run time a method can be invoked which does the initilization and hence compile time detection if value is not provided by the programmer is not possible and hence compiler chooses the safe option of allowing usuage and provides the default value in case method or constructor which handles the initilization is not invoked.
Non final local variable can only be initilized within it's method. There is not much point of making a non final variable if user wants to use the default value. It makes more sense to use the value directly or use a final keyword. If a non final local variable has been used then compiler forces the user to provide the initial value which may or may not be the default value.
For final fields both instance level and local, compiler forces the user to provide the initial value.

You need to initialise only local variables or class level variables declared final as per the java language spec. They won't be initialised with default values.

Related

What is true reason for initiliazing need of final varibles before use

I know that:
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.
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.
Why final variable cannot be assigned just once at any time instead of just at declare time?
The corollary to this, for non-final variables, is the initial value of a variable. Every field receives an initial value depending on its type - usually a variant of 0 or null.
It's implied here that, if you're declaring a variable to be final, then you have a specific value in mind that you wish that variable to be assigned and not have changed later in its run. Java doesn't know what value that is, and it likely takes away the convenience of automatically declaring those values for you so to not interfere with the developer's intentions.
That and requiring that all final variables be initialized is to support all variables being definitely assigned before their use. You can use a non-final field that you don't initialize to some value - it'll likely be null though - but you can't use a local variable that you haven't initialized yet for the same reason.
First it is not something against null. The following is legal too:
final String ABC;
{
ABC = null;
}
static final String DEF;
static {
DEF = null:
}
final String GHI = null;
It was the following decision:
When a final field or a local variable is not initialized it can very
well be a bug, forgetting to initialize.
(For normal fields it would be too much boiler code, and zeroing of fields is provided.)
For local variables you might find this obvious. As final variables can only be assigned once, and it was decided that this should happen only during construction (otherwise you would need administration of whether the variable was initialized).
Language design decisions are always a trade off between flexibility and error prevention. In this case, there are some simple questions to check:
In case, there is a code path in which a final variable is not assigned:
How likely is it that the developer declares a final variable just to hold the default value, null, 0 or false?
In contrast, how likely is it that the developer has forgotten the initialization or overlooked a possible code path, in other words, rejecting this code prevents a nasty bug?
How much work is it for the developer, to write the explicit assignment, if (s)he really wants the default value?
I think, trying to answer these questions should lead to the rationale behind this design decision.
This is the place for an important clarification. In case of local variables, all variables must be initialized before use. The restriction is only lifted for non-final heap variables, read, fields and array elements.
In case of arrays, it should be obvious why developers are not enforced to write explicit default values when arrays can be instantiated for lengths up to 2³¹ elements. For non-final instance fields, this decision can be discussed. But such a discussion would be outside the scope of Stackoverflow…

How can removing final keyword change the way a program behaves?

This question is not primarily about Strings. Out of academic curiosity I would like to know how the final modifier on a variable can change the behaviour a program. The following example shows it is possible.
These lines print true
final String x = "x";
System.out.println(x + x == "xx");
but these lines print false
String x = "x";
System.out.println(x + x == "xx");
Apart from String interning, are there any other things that can cause the behaviour of a program to change if the modifier final is removed from a variable declaration? I am assuming that the program compiles with or without the modifier.
Please don't vote to close it as duplicate of Comparing strings with == which are declared final in Java. I understand the Strings example.
I'm asking if there are any other reasons removing a final modifier can make a difference. Please can someone link to an answer or answer the question. Thanks.
The final modifier only ensures that the variable is definitely assigned, and prohibits any reassignment to and from that variable.
The only special cases that can be observed are expressly stated in the JLS:
A variable of primitive type or type String, that is final and initialized with a compile-time constant expression (§15.28), is called a constant variable.
Whether a variable is a constant variable or not may have implications with respect to class initialization (§12.4.1), binary compatibility (§13.1, §13.4.9) and definite assignment (§16).
There's a decent amount of JLS reading, and to cover the main point: By JLS §13.4.9, you will not encounter any ill effects upon removing the final modifier.
However, by JLS 17.5, if you rely on the guarantee of a thread only seeing the definitely assigned variables in an object that it can observe, then removing the final variable will cause those variables to no longer be visible to another thread.
So, if we look at class initialization first, there are rules surrounding class initialization if the field is static and not a constant variable:
A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
T is a class and an instance of T is created.
T is a class and a static method declared by T is invoked.
A static field declared by T is assigned.
A static field declared by T is used and the field is not a constant variable (§4.12.4).
In JLS §13.1, it is spelled out that changing a field to final can break binary compatibility:
References to fields that are constant variables (§4.12.4) are resolved at compile time to the constant value that is denoted. No reference to such a field should be present in the code in a binary file (except in the class or interface containing the field, which will have code to initialize it). Such a field must always appear to have been initialized (§12.4.2); the default initial value for the type of such a field must never be observed. See §13.4.9 for a discussion.
From 13.4.9:
If a field that was not declared final is changed to be declared
final, then it can break compatibility with pre-existing binaries that
attempt to assign new values to the field.
Deleting the keyword final or changing the value to which a field is
initialized does not break compatibility with existing binaries.
If a field is a constant variable (§4.12.4), then deleting the keyword
final or changing its value will not break compatibility with
pre-existing binaries by causing them not to run, but they will not
see any new value for the usage of the field unless they are
recompiled. This is true even if the usage itself is not a
compile-time constant expression (§15.28).
This result is a side-effect of the decision to support conditional
compilation, as discussed at the end of §14.21.
So from that alone, be careful about suddenly changing fields to final. Removing the field is safe.
...but that only applies to a single-threaded world. From JLS 17.5:
Fields declared final are initialized once, but never changed under
normal circumstances. The detailed semantics of final fields are
somewhat different from those of normal fields. In particular,
compilers have a great deal of freedom to move reads of final fields
across synchronization barriers and calls to arbitrary or unknown
methods. Correspondingly, compilers are allowed to keep the value of a
final field cached in a register and not reload it from memory in
situations where a non-final field would have to be reloaded.
final fields also allow programmers to implement thread-safe immutable
objects without synchronization. A thread-safe immutable object is
seen as immutable by all threads, even if a data race is used to pass
references to the immutable object between threads. This can provide
safety guarantees against misuse of an immutable class by incorrect or
malicious code. final fields must be used correctly to provide a
guarantee of immutability.
An object is considered to be completely initialized when its
constructor finishes. A thread that can only see a reference to an
object after that object has been completely initialized is guaranteed
to see the correctly initialized values for that object's final
fields.
So, if your program relies on the above guarantee for it to function normally, then removing the final keyword will have consequences in threading.

what's the difference between those two ways to initialize fields in Java?

Assign value to field at the same time with field declaration
Assign value to field in the constructor?
What's the difference between those two ways to initialize fields in Java?
Not much! The main difference is that if you assign it at the point of declaration, it will apply to all constructors. That is, there's no way you can forget to add the initialization to any future constructors.
Have a look at the official Initializing Fields trail.
May be worth noting that if you initialize the fields at the declaration, it happens before the constructor starts executing.
As a rule of thumb, I usually initialize the "dead simple" fields at the declaration (when there is no doubt what the initial value should be). This "cleans up" For instance
class SomeClass {
List<Integer> currentNumbers = new ArrayList<Integer>();
int counter = 0;
// ...
}
while as if there is the slightest chance that I may want different behaviors in different constructors, I leave it to the constructor.
In both cases, the value will only be assigned after the superclass constructor has executed.
For the first option, you have to be able to determine the value without reference to any constructor parameters.
For the second option, you'll need to assign the value in every constructor overload.
Basically I tend to favour the second option when the value depends on constructor parameters (usually that's all I would want it to depend on) and the first option when the value will be the same for any newly initialized instance. I tend not to mix and match for a single field, using an initializer with the declaration and also assigning it in some constructor overloads, but even that can be useful occasionally. (Imagine a collection which has a size of 0 for most constructors, but has one constructor which takes an initial set of values.)
While you can refer to other instance members in variable declarations, I prefer not to - calling instance methods when your object is only partially initialized is brittle, and referring to other variables relies on the variable ordering, which feels ugly to me.
(1) is a syntax sugar for (2) (with the exception of static fields)
It does exactly the same, just at different times in the object instantiation life-cycle. Have a look here for more information.
In the first case the field will be created when the class is initialised and assigned directly the value you hace declared for it, while in the second case the field will be created and assigned a default value (null if it's an object, 0 if it's an int, etc.) and then assigned the correct value when the constructor is executed. Of course practically there's usually not much difference for you since the result in both cases is the same: when you create an instance of this class after the constructor returns the field is initialised correctly. I guess the first approach would be more usefull if you have more than one constructors and a field which should have the same value regardless of which constructor has been called.

What is the difference between local and instance variables in Java?

Except the scope and the storage differences, are there any other major difference between instance and local variables in Java?
The main differences that I see are in their:
Scope: Local variables are visible only in the method or block they are declared whereas instance variables can been seen by all methods in the class.
Place where they are declared: Local variables are declared inside a method or a block whereas instance variables inside a class, but outside a method.
Existence time: Local variables are created when a method is called and destroyed when the method exits whereas instance variables are created using new and destroyed by the garbage collector when there aren't any reference to them.
Access: You can't access local variables, whereas instance variables can be accessed if they are declared as public.
Where they are declared: Local variables are declared in a method or a block before they are called, whereas instance variables can be declared anywhere in the class level (even after their use).
Instance variables always have value, even if they are not assigned by the code (then they will have for example null, 0, 0.0, and false). For local variables, there must be an assigned value by the code. Otherwise the compiler generates an error.
One extra thing I can think of:
Instance variables are given default values, i.e., null if it's an object reference, and 0 if it's an int.
Local variables don't get default values, and therefore need to be explicitly initialized (and the compiler usually complains if you fail to do this).
One other difference is you don't have to worry about concurrent access to local variables; whereas you do with instance variables in a multi-threaded environment.
No, you pretty much covered it. An instance variable belongs to an instance of a class, and a local variable belongs to a stack frame.
Instance variables are initialized to default values, but it's generally good practice to use explicit initializations anyway.
A local variable:
is declared inside a method/constructor or within a block (enclosed in braces)
must be initialized before use. Otherwise it won't compile.
An instance variable:
is declared inside a class.
initialization is not compulsory: if omitted, it contains the default value (0, 0.0, false, null, etc.)
-> local variable is declared in the body of a method and can be used
only from the point at which it’s declared through the end of the method
declaration.
-> An instance variable is declared in a class, but not in the body
of any of the class’s methods. Also, instance variables are accessible to all
methods of the class.
Aside from all that is already mentioned here, I would like to point out that local variables are a bit faster to access for the JVM. The JVM has got more work to do to read or write an instance variable compared to a a local variable.
This is still true for the current HotSpot server JVM, because it's not a VM optimization problem. It's rather caused by the fact that an instance variable is visible outside of the method and could thus be accessed from other threads while the method is executed.
Aside from all the differences mentioned in previous answers, I would like to point out one more difference that, instance variables can have access modifiers (like private, public, protected, etc.), but local variables will not have any access modifiers.
Local variables are on the stack, but member variables (instance variables) are on the heap.
Variables defined inside methods, constructors or blocks are called local variables. The variable will be declared and initialized within the method and it will be destroyed when the method has completed.
Instance variables are variables within a class but outside any method. These variables are instantiated when the class is loaded.
Local variables are declared within a method.
Instance variables are declared inside a class but not within a method.
Local variables do not get a default value. The compiler complains if you try to use a local variable before before the variable is initialised.
However, instance variables always get a default value. If you don't explicitly assign a value to an instance variable, the instance variable still has a value.
integers 0
floating points 0
Boolean false
references null
The main difference is instance variables get default values. Like an int value gets zero and a char gets a null, but not the local variables.
You can leave uninitialized instance variable, but where as local variables must be initialized otherwise you will get compiler error.
Existence time:
I would like to tell you the major important difference between these variables is that when I encountered a problem where my instance variable during my software development worker life. Problem was occurring when user log in I have to return a username of user, who log in, but there is a problem, where for example one user log in it work successful but when another user log in while program run it return again a username, which log in before. I did run the program like debug mode and I could see a problem within my instance variable, which it could be local variable in my authentication method. The reason I tell that be careful when you work local and instance variable in programming language. All programmers don't take enough time simply topics, but small problems create great complexity.

Default values of instance variables and local variables

I read that Java provides default values to class properties, but not to local variables. Is that correct?
If so, what is the reason behind this? When you are doing something good, why not do it all the way?
Standard local variables are stored on the stack and aren't actually created until they are initialized. If a local variable isn't used, it doesn't go on the stack. Member variables, however, are allocated in the heap, and thusly have a default placeholder (null reference or default primitive).
The non-technical reason behind may also be the following one:
If you declare a local variable, you do this in order to use it. And usage is connected with assigning a value. Therefore, accessing a declared, but not initialized, variable does not make that much sense - the programmer might simply have forgotten to initialize the variable.
Fields, however, might only be used until or after a specified point in the object's lifetime. Forcing the programmer to initialize them all would not be good.

Categories

Resources