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.
Related
I was learning about using this() to call an overloaded constructor and came across this restriction:
You can not use any instance variable of the constructor's class in a call
to this()
For example:
class Test{
int x;
public Test() {
this(x); //Does not compile
}
public Test(int y) {}
void method1() {
method2(x); //OK
}
void method2(int y) {}
}
I know that no need to pass an instance field to a constructor since it's visible by default. However, why is the same restriction not applied to instance methods?
There is one other requirement in Java: constructor calls (using this() must be performed first within any constructor. The constructors will initialize the object.
After that the instance fields are initialized after these initial calls. So as the field values are now well defined, you can use them for anything including calling other methods.
However, before the initial constructor calls, the fields are in an undefined state and cannot be used as argument for other constructor calls.
For these kind of things you need to look in the JLS:
If this constructor begins with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.
Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.
So the instance variables are only initialized after the constructor calls. This makes sense, because it would be strange to first assign it the default value (zero or null) and then assign it another value from within a constructor.
The constructor constructs the instance. So we shouldn't expect the instance variable x to be initialized at the time the constructor starts.
On the other hand, an instance method can already access instance variables. There is no reason to forbid passing them as a parameter into another instance method.
However, when we start to think about it a bit further, that restriction on the constructor doesn't make that much sense anymore. We are able to access instance variables there as well, so why shouldn't we be able to pass it a parameter to another constructor?
So a better question to ask is: Why can't we pass an instance variable to call an overload of our constructor from within our constructor?
And this question has been beautifully answered. It could even be considered a duplicate (but since that pretext is neccessary to understand why, I wrote an answer instead of simply flagging).
The instance fields that are declared and initialized in the class body outside of the constructor, like your int x; are assigned after the call to the overloaded constructor.
You can compare that to the other restriction we have about calling constructor overloads: We can only do so in the first line of our constructor. Right at the start. And then, the variables are not yet initialized. But they are initialized right before the first non-constructor-call instruction.
Tangential information to why this other restriction is a thing can be found here and there:
Because the JLS says so. Could the JLS be changed in a compatible manner to allow it? Yup.
Historically, this() or super() must be first in a constructor. This
restriction was never popular, and perceived as arbitrary. There were
a number of subtle reasons, including the verification of
invokespecial, that contributed to this restriction. Over the years,
we've addressed these at the VM level, to the point where it becomes
practical to consider lifting this restriction, not just for records,
but for all constructors.
You should be educating the class order initialization f.e: https://www.baeldung.com/java-initialization
The int x field is not initialized when the class constructor is called. You can set (initialize) `int x 'in your constructor, but not call it.
I don't know why you have to follow this way, but you can use the static field:
class Test{
static int x;
public Test() {
this(x); //Does not compile
}
public Test(int y) {}
void method1() {
method2(x); //OK
}
void method2(int y) {}
}
You can also initialize a static field in the line where it is called,
static int x =4/2;
or in static block:
static int x;
static {
x = 4/2;
}
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.
I'm indebted to this answer for the idea.
The following code compiles, but certainly shouldn't. It uses the value of x before it's been initialised. If you remove the StaticAssign. qualifier then it no longer compiles.
public class StaticAssign {
public static final int x;
static {
System.out.println(StaticAssign.x);
x = 5;
}
public static void main(String[] args) {}
}
On my machine, this consistently prints 0. If I change the type of x to String, it consistently prints null.
The question is: will it definitely print 0 or null, or might it access uninitialised memory and print out something else?
And even if this code gets through the compiler, why isn't it picked up by the JVM?
Is there a way to do nasty things based on this?
It actually has been initialized. Variables in the global scope are initialized automatically. Variables of Object type will be initialized to null primitive like int will be initialized to 0. A variable declared not in the global scope must be initialized ie. declared in a method. Another problem is declaring it as final this is telling the compiler it must be explicitly initialized. So by adding the x=5 you are bypassing the compiler error saying it must be explicitly initialized. When you access it before this line at run-time it is initialized to 0 like any other primitive int type variable in the global scope.
This is due to the way in which the classes are loaded.
First the class StaticAssign definition is loaded and the fields are initialized to default values:
StaticAssign.x = 0;
Then the initalization block is executed.
System.out.println(StaticAssign.x);
x = 5;
There is a reference to StaticAssign.x, the current class. As recursive initialization attempts are simply ignored, value of x is still 0.
This means that:
System.out.println(StaticAssign.x)
is valid because StaticAssign.x is a reference to field of an allready loaded class.
But if yo do:
System.out.println(x)
then x is a reference to a final uninitalized field.
On the other hand, you never will access uninitialised memory. When the class definition is loaded variables are initialized to default values, before the initalization block is executed.
EDIT:
There is a nice video "Elvis Lives Again" from Java Puzzlers that shows this much more better than I can explain
Is there any difference between the following types of instantiation?
Whether I set the value directly where the variable is defined, or in the class constructor.
If not, what is best practice?
"In class":
class A {
boolean b = true;
public A(){
}
}
"In constructor":
class B {
boolean b;
public B(){
b = true;
}
}
The variable type is just for the example.
The only difference I see is, when the attribute is a complex type (a class) which constructor depends on values that are given to the constructor of the containing class:
class A {
B b;
public A(String s){
b = new B(s);
}
}
Actually they both are equivalent. From a readability point of view, however, the first one is more readable. Also, it's easy to see the default value when someone navigates to the variable declaration from an IDE (like ctrl + mouse-click in Eclipse).
Check out what the official tutorial has to say -
This works well when the initialization value is available and the
initialization can be put on one line. However, this form of
initialization has limitations because of its simplicity. If
initialization requires some logic (for example, error handling or a
for loop to fill a complex array), simple assignment is inadequate.
Instance variables can be initialized in constructors, where error
handling or other logic can be used. To provide the same capability
for class variables, the Java programming language includes static
initialization blocks.
So you can easily use the simple one-liner initialization technique when the process is simple. For complex initialization choices, constructors are the way to go.
If you assign the value to variable in the class, then while creating instance of the class, directly your desired value will get assigned to the variable.
If you assign values in the constructor, then your variables will be first assigned a default value and then the values from constructors will get assigned.
Read on initialization blocks, constructors and their order of execution
In case of best practice,
If passing all the values to the costructor is must while creating the object, then construction initialization must be used.
If there are some values which need to be default for every object, then you can assign outside constructors.
Use an initialization block. Initializing Fields
public class X {
// The following is the initializer block
{
}
public X() {
}
}
Instance variables are assigned default values in case you don't assign one! Bu default boolean instance variables are assigned value false.
public class HelloWorld {
boolean b;
public void printData() {
System.out.println("Defualt boolean value is " + b);
}
public static void main(String args[]) {
HelloWorld hw = new HelloWorld();
hw.printData();
}
}
and the output is Defualt boolean value is false.
Where are you assigning your variable is purely a design choice.
Both are almost same.
But an effective line from docs
. Instance variables can be initialized in constructors, where error handling or other logic can be used.
Instance field initializations are copied to the start of the constructor by the compiler, so the first two approaches generate the exact same code (or pretty darn close).
(Note however that the above is not quite true for static field initializations vs the static initializer method.)
It's mainly a question of which seems clearer and less likely to lead to confusion/errors down the road. And that depends on numerous factors, including personal style.
I'd recommend C:
class C {
private boolean b = true;
}
-> no (explicit) constructor -> less code -> easier to read
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.