Why aren't default values assigned to the variables, that haven't been initialized within a Class with main function???
class Test {
public static void main(String[] args) {
int x;// x has no default value
String y;// y has no default value
System.out.println("x is " + );
System.out.println("y is " + );
}
}
Whereas the default values get assigned in case the variables remain uninitialized in a class without any main function.
class Student {
String name; // name has default value null
int age; // age has default value 0
boolean isScienceMajor; // isScienceMajor has default value false
char gender; // c has default value '\u0000'
int x;
String y;
}
Be aware that the code in the question represents different situations. In the first case, the variables are local and exist inside the main() method. In the second case you're declaring instance attributes, not local variables.
In Java, only the attributes are initialized automatically with default values. In all the methods, even in the main() method, you must explicitly provide an initialization value for the variables declared locally inside the method.
This is explained in the Java Language Specification, section §4.12.5:
Each class variable, instance variable, or array component is initialized with a default value when it is created (§15.9, §15.10)
Each method parameter (§8.4.1) is initialized to the corresponding argument value provided by the invoker of the method (§15.12)
Each constructor parameter (§8.8.1) is initialized to the corresponding argument value provided by a class instance creation expression (§15.9) or explicit constructor invocation (§8.8.7)
An exception parameter (§14.20) is initialized to the thrown object representing the exception (§11.3, §14.18)
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)
To see several reasons why local variables are not initialized automatically, please take a look at this previous question.
The basic reason is that, in order to catch a common programmer error, the Java authors decided to ensure that every variable is assigned before it is used. However, it is not possible to enforce this for fields, so they had to spec default values for fields.
You do get an error if you use a field in a constructor before it is initialized, but there is no way for the compiler to prevent this:
class C {
int f;
C() {
init();
}
void init() {
System.out.println(f);
}
}
When the JVM is creating the new object instance, it has to allocate memory for the attributes because they are part of the class itself. The mere existence of a Java primitive int requires 4 bytes of memory to be allocated, whereas an Integer can be set to null since it's an object. That's why classes must have their attributes set to something upon being initialized.
Reading the value of a variable before it has been given a value is a common source of bugs. Forcing you to assign a value before using a variable makes programs safer: you'll know you'll get the value you expect and not some default value just because you didn't anticipate a certain program flow.
Unfortunately the liveness analysis that implementing this needs can only be done for local variables, and you can access instance fields before the program has initialized them with a value. To avoid unpredictable behavior the JVM initializes instance fields to default values.
Related
Consider the following code snippet in Java. It won't compile.
package temppkg;
final public class Main
{
private String x;
private int y;
private void show()
{
String z;
int a;
System.out.println(x.toString()); // Causes a NullPointerException but doesn't issue a compiler error.
System.out.println(y); // Works fine displaying its default value which is zero.
System.out.println(z.toString()); // Causes a compile-time error - variable z might not have been initialized.
System.out.println(a); // Causes a compile-time error - variable a might not have been initialized.
}
public static void main(String []args)
{
new Main().show();
}
}
Why do the class members (x and y) declared in the above code snippet not issue any compile-time error even though they are not explicitly initialized and only local variables are required to be initialized?
When in doubt, check the Java Language Specification (JLS).
In the introduction you'll find:
Chapter 16 describes the precise way in which the language ensures
that local variables are definitely set before use. While all other
variables are automatically initialized to a default value, the Java
programming language does not automatically initialize local variables
in order to avoid masking programming errors.
The first paragraph of chapter 16 states,
Each local variable and every blank final field must have a definitely
assigned value when any access of its value occurs....A Java compiler
must carry out a specific conservative flow analysis to make sure
that, for every access of a local variable or blank final field f, f
is definitely assigned before the access; otherwise a compile-time
error must occur.
The default values themselves are in section 4.12.5. The section opens with:
Each class variable, instance variable, or array component is
initialized with a default value when it is created.
...and then goes on to list all the default values.
The JLS is really not that hard to understand and I've found myself using it more and more to understand why Java does what it does...after all, it's the Java bible!
Why would they issue a compile warning?, as instance variables String will get a default value of null, and int will get a default value of 0.
The compiler has no way to know that x.toString(), will cause a runtime exception, because the value of null is not actually set till after runtime.
In general the compiler couldn't know for sure if a class member has or has not been initialized before. For example, you could have a setter method that sets the value for a class member, and another method which accesses that member. The compiler can't issue a warning when accessing that variable because it can't know whether the setter has been called before or not.
I agree that in this case (the member is private and there is no single method that writes the variable) it seems it could raise a warning from the compiler. Well, in fact you are still not sure that the variable has not been initialized since it could have been accessed via reflexion.
Thins are much easier with local variables, since they can't be accessed from outside the method, nor even via reflexion (afaik, please correct me if wrong), so the compiler can be a bit more helpful and warn us of uninitialized variables.
I hope this answer helps you :)
Class members could have been initialized elsewhere in your code, so the compiler can't see if they were initialized at compilation time.
Member variables are automatically initialized to their default values when you construct (instantiate) an object. That holds true even when you have manually initialized them, they will be initialized to default values first and then to the values you supplied.
This is a little little lengthy article but it explains it: Object initialization in Java
Whereas for the local variables (ones that are declared inside a method) are not initialized automatically, which means you have to do it manually, even if you want them to have their default values.
You can see what the default values are for variables with different data types here.
The default value for the reference type variables is null. That's why it's throwing NullPointerException on the following:
System.out.println(x.toString()); // Causes a NullPointerException but doesn't issue a compiler error.
In the following case, the compiler is smart enough to know that the variable is not initialized yet (because it's local and you haven't initialized it), that's why compilation issue:
System.out.println(z.toString()); // "Cuases a compile-time error - variable z might not have been initialized.
so I think I'm missing something. I am aware that
If no constructor is supplied java makes one for you.
If there's a constructor defined, default constructor by java is not used.
Constructor is used to initialize variables
Here's some simple code:
class a {
int f; // a variable with no value
int c; // a variable later initialized by the constructor
int b = 5; // this will be second question, a less important one
a(){
c = 1; // Constructor initiatives C, but not F
}
public static void main(String[] args){
a var = new a();
System.out.print(var.f); // Please see my comment below
}
}
Here's what I do not understand. Why is var.f printed? I did not initialize f in the constructor, however, there's no compile error and 0 value is initialed. I don't understand how '0' is initialized to 'f' despite me not having used it in constructor
Regarding b = 5, I understand what this code leads to, however, I do not think I understand what/who does the initialization here, is it new operator or something else? Thanks.
Edit: since the answers so far are not addressing my question
I am aware of the default values. I thought it was the default constructor that assigned them, is it not? If not, what assigns default values?
Java like most of programming languages has default values for uninitialized variables. Every numeric type of variable is initialized to 0-related value.
Boolean is false as default.
Strings and all of the objects have null as their default value.
Check docs for more info: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
int is a primitive data type. By definition, primitives cannot be null as they are not objects and will have a default value if not initialized. See here: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
If you want to be able to have a variable that is not initialized, you can use the object equivalent of an int java.lang.Integer
Instance variables that are declared but not initialised are given a default value.
References take a default value of null.
Primitives take a default value of zero
In regards to your query on your primitive int variable b, the new operator is not required, the new operator is used when instantiating a reference. When an instantiating a reference an object is created and memory is allocated on the JVM for that object.
Strings are a reference variable, but may be instantiated using the new keyword for example:
String example = new String("abc");
System.out.println(example); // prints abc.
Usually you would just write:
String example = "abc";
In the latter the literal is placed in to the 'string pool'...
You can read more about the string pool here: http://examples.javacodegeeks.com/core-java/lang/string/java-string-pool-example/
If no constructor is supplied java makes one for you.
Correct.
If there's a constructor defined, default constructor by java is not used.
It is not generated.
Constructor is used to initialize variables
Correct.
c = 1; // Constructor initiatives C, but not F
Untrue. Your code initializes c. The generated constructor initializes both.
I did not initialize f in the constructor
No, but Java did.
Java generates the following code for a constructor:
A super call.
Default initialization code for all variables declared without initializers. The default values are false, zero, or null as appropriate to the type.
Calls to all anonymous initializer blocks. (2) and (3) happen in textual order and can therefore be interleaved with each other.
Regarding b = 5, I understand what this code leads to, however, I do not think I understand what/who does the initialization here, is it new operator or something else?
See above.
I am aware of the default values. I thought it was the default constructor that assigned them, is it not?
No.
If not, what assigns default values?
The constructor. Any constructor.
In Java, what is the difference and best way to do?
Integer x = null; // x later assign some value.
Integer y; // y later initialize and use it.
The answer depends on what type of variable are you referring.
For class variables, there's no difference, see the JLS - 4.12.5. Initial Values of Variables:
... Every variable in a program must have a value before its value is
used:
For all reference types (§4.3), the default value is null.
Meaning, there is no difference, the later is implicitly set to null.
If the variables are local, they must be assigned before you pass them to a method:
myMethod(x); //will compile :)
myMethod(y) //won't compile :(
Local variables must be assigned to something before they are used.
Integer x = null;
myFunction(x);
// myFunction is called with the argument null
Integer y;
myFunction(y);
// This will not compile because the variable has not been initialised
Class variables are always initialised to a default value (null for object types, something like zero for primitives) if you don't explicitly initialise them. Local variables are not implicitly initialised.
Its better to not set it to null, otherwise you can by accident use it and cause NPE. Compiler wont help you with compile error. Only set to null if you want to have logic like if ( x != null ) { /use it/ }
No difference at all. Both cases when ever you want to use it, local variable must be in initialized form(must have a value).
From Java doc
Similar to how an object stores its state in fields, a method will
often store its temporary state in local variables. The syntax for
declaring a local variable is similar to declaring a field (for
example, int count = 0;). There is no special keyword designating a
variable as local; that determination comes entirely from the location
in which the variable is declared — which is between the opening and
closing braces of a method. As such, local variables are only visible
to the methods in which they are declared; they are not accessible
from the rest of the class.
Internally there is no difference. Also it is a debatable topic.
Use the local variable only if it is really required. Local variables are mostly in the following scenarios (I may be missing few other).
As a shorthand or for Readability
Integer myObject = someObject.someFunction().someOtherFunction();
If we use the syntax like that in many places, code will become clumsy.
For accessibility
Object returnObject = null;
if(mycondition)
{
returnObject = value1;
}
else if(secondCondition)
{
returnObject = value2;
}
return returnObject;
The caller of the above code snippet will take decision based on the return value.
Honestly speaking i am not seeing other valid use case to declare a variable without initial value.
Conclusion (Best Practice):
Declare local variable only if required
Always create local variable with default value.
No differences at all expect for one thing, if you don't initialize it and later on you try to use this variable (without changing the reference) means an error at compilation time, but if you initialize it and you use it later on (without changing the reference) means a NullPointerException.
I show you with an example.
Without initializing
Integer y;
y.intValue(); // Compilation error
With initializing
Integer x = null;
x.intValue(); // You are able to compile it but NullPointerException
we know that...
Instance Variable are initialized in default constructor. For eg.
public class H{
int x;
public static void main(String... args){
System.out.print(new H().x);
}
}
The O/P of above code is 0 because there is a default constructor which is called , and that constructor initialized the x to 0.
Now, my question is, if we run the below code, i.e.
public class H{
int x;
public H(){}
public static void main(String... args){
System.out.print(new H().x);
}
}
The actual O/P is 0 in this case also, but I think there should be compiler error that x is not initialized, because we have override the default constructor and didn't initialize x.I think I have made my question clear..
In Java, instance members are defaulted to the all-bits-off version of their value automatically (ints are 0, object references are null, floats are 0.0, booleans are false, and so on). It's not something the default constructor does, it's done before the constructor runs.
The order is:
Default the instance members to their all-bits-off value. (The optimizer can skip this if it sees #2 below or possibly if it can prove to itself that nothing uses the member prior to an initialization per #3 below.)
Apply any inline initialization of them. For instance:
int a = 42;
Apply instance initialization blocks in source code order.
Call the appropriate constructor.
So for example:
class Example {
int a = 42;
// Instance initializer block:
{
this.a = 67;
}
Example() {
System.out.println(this.a);
}
}
new Example() outputs 67.
Obviously, initializing in both places like that would be poor practice, this is just for illustration.
Non-final fields are initialized by default in java. Only variables inside methods and final fields are not initialized by default.
If you had declared x to be final, then you would be correct. You would have a compile error in the code.
All instance level variables are initialized to their default values irrespective of whether the constructor has been overloaded ( or explicit no-argument constructor has been added). The constructor merely changes the default value(s).
Instance variables have default values associated with them
From The Java™ Tutorials:
Default values
It's not always necessary to assign a value when a field is declared. Fields that are declared but not initialized will be set to a reasonable default by the compiler. Generally speaking, this default will be zero or null, depending on the data type.
Java is quite neat to programmers (unlike others, C for instance), this means that it initializes fields automatically. An exception is final fields and fields inside a methods (where the compiler will then produce an error).
Hope it helped.
Java doesn't allow you to use an variable that may not have been initialized within a method scope. An uninitialized variable within a class scope may still be returned by a class method, and the value defaults to null.
Why the different treatment of the two different scopes?
public class TestClass {
Integer i;
Double d;
public TestClass() {
d = 1d;
}
public Double getD() {
return d;
}
public Integer getI() {
return i;
}
// public Integer getSomeInt() {
// Integer i;
// return i;
// }
public static void main(String[] args) {
TestClass myClass = new TestClass();
System.out.println(myClass.getI().getClass());
}
}
This results in a NullPointerException, but returning i within getSomeInt() is a compiler error because "the variable may not have been initialized".
The reason behind this are the limits of Java's static code analysis. The compiler is able to prove beyond doubt that you will not read a stack-allocated local var before initializing it. This is impossible to do for heap-allocated memory and therefore Java mandates that all heap-allocated storage be zeroed out before exposing a pointer to it.
The consequence of this rule is that everything heap-allocated has a default value of zero (false, null, whatever the binary zero amounts to for the type).
Because member variables have default value (if not initialized) and so the I has null and if you invoke method on null it will result on NullPointerException
and for local variables, they must be initialized before used otherwise it will turn into compile time error
Local variables are slightly different; the compiler never assigns a default value to an uninitialized local variable. If you cannot initialize your local variable where it is declared, make sure to assign it a value before you attempt to use it. Accessing an uninitialized local variable will result in a compile-time error. [....]
It's quite simple really. Member variables get automatically initialized to their default values, while local variables does not.
When you do
public Integer getSomeInt() {
Integer i;
return i;
}
you hide this.i and in return i you refer to an (uninitialized) local variable.
So why are member variables initialized automatically while local variables are not?
Ultimately this is a question that only the designers of the language can answer, but if I had to guess I'd say it is due to the performance issue of having to zero out all memory being allocated. When it comes to objects, it would however be a pain to force the programmer to initialize all fields explicitly.
From the JLS (4.12.3 Kinds of Variables):
A class variable is created when its class or interface is prepared (§12.3.2) and
is initialized to a default value (§4.12.5).
[...]
A local variable declaration statement may contain an expression which
initializes the variable. The local variable with an initializing expression is
not initialized, however, until the local variable declaration statement that
declares it is executed. (The rules of definite assignment (Chapter 16, Definite
Assignment) prevent the value of a local variable from being used before it has
been initialized or otherwise assigned a value.)
All fields are implicitly initialized in the constructor after the call to super but before anything else. Object references are set to null, primitive values are set to 0, false etc.
This implicit initialization isn't done in methods.