Is there any difference between these two ways of initialising class members?
In the class body:
public class A {
private mB = new B();
public A() {
}
}
Or in the constructor:
public class A {
private mB = null;
public A() {
mB = new B();
}
}
In theory, there is a difference in the sequence of initialization. This is the sequence used by the JVM:
Static statements/static blocks are executed.
Instance variables are assigned default values
Instance variables are initialized if the instance variable is assigned a compile time constant. Otherwise, it will be done with Item 5 (instance variables and instance initializers will be done together from the top to the bottom, in the order they are defined).
constructor runs
Instance initialization block(s) run after all the call(s) to super has(have) been completed but before the rest of the constructor is executed.
Rest of the constructor is executed.
Also, if you initialize the fields in the constructor, it can mean that you might get some duplication. Personally, I think it doesn't matter much where you instantiate them, either in the constructor or in the fields, but the main point is that you are consistent about it. For me it helps having them instantiated in the field declaration so I know which fields are always there, and which fields are optional. Hope that helps!
The instance initializer run first and then values in constructor are initialized. You can study order of execution of initialization blocks and constructors
If B() constructor threw a checked exception then this
private mB = new B();
would be a compile time error, while in constructor you could catch it or declare in throws clause
I would do the one you believe is simpler.
The main difference is that if you add another constructor to the first, you don't have to repeat the initialisation.
Your first example initializes the variable once: your second example, twice. First is to be preferred, especially if there are multiple constructors, unless there is an exception involved of course.
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;
}
In the code below, what is the order of initialization of data fields? What is the general rule followed by java for data member and member functions?
public class TestClass
{
int j=10;
static int h=5;
public static void main(String[] args)
{
TestClass obj= new TestClass();
}
}
In general:
1) static field members (static initializers in general)
2) non-static field members
3) constructor
However you can test it with a snippet of code like this:
public class TestClass {
int i = 10;
static int j = 20;
public TestClass() {
// TODO Auto-generated constructor stub
System.out.println(i);
i = 20;
System.out.println(i);
}
public static void main(String[] args) {
new TestClass();
}
}
Quoting from the great "Thinking In Java":
Within a class, the order of initialization is determined by the order that the variables are
defined within the class. The variable definitions may be scattered throughout and in between method definitions, but the variables are initialized before any methods can be
called—even the constructor.
...................................
There’s only a single piece of storage for a static, regardless of how many objects are created.
You can’t apply the statickeyword to local variables, so it only applies to fields. If a field is a
staticprimitive and you don’t initialize it, it gets the standard initial value for its type. If it’s
a reference to an object, the default initialization value is null.
To summarize the process of creatingan object, consider a class called Dog:
Even though it doesn't explicitly use the static keyword, the constructor is actually a
static method. So the first time an object of type Dog is created, or the first time a
static method or static field of class Dog is accessed, the Java interpreter must
locate Dog.class, which it does by searching through the class path.
As Dog.class is loaded (creating a Class object, which you’ll learn about later), all of
its static initializers are run. Thus, static initialization takes place only once, as the
Class object is loaded for the first time.
When you create a new Dog( ), the construction process for a Dog object first
allocates enough storage for a Dog object on the heap.
This storage is wiped to zero, automatically setting all the primitives in that Dog
object to their default values (zero for numbers and the equivalent for boolean and
char) and the references to null.
Any initializations that occur at the point of field definition are executed.
Constructors are executed.This might actually involve a fair amount of activity, especially when inheritance is involved.
Here is the order.
Static fields initialized and static block executed at class loading time, they will be initialized in the same order they declared.
Set fields to default initial values (0, false, null)
Call the constructor for the object (but don't execute the body of the constructor yet)
Invoke the constructor of the superclass
Initialize fields using initializers and initialization blocks
Execute the body of the constructor
I think you're just missing section 12.4.2 of JLS, which includes:
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.
The "in textual order" part is the important bit.
If you change m from being static variable to an instance variable, then the field won't be initialized by class initialization - it'll only be initialized by instance initialization (i.e. when an instance is constructed). At the moment, that'll cause a stack overflow - creating one instance requires creating another instance, which requires creating another instance, etc.
So Finally Here is Order which you are searching for:
Initialization blocks run in the order they appear in the program.
Static initialization blocks run when the class is first loaded into JVM
Instance initialization blocks run whenever a new instance of class is created.
As per standard book constructor is a special type of function which is used to initialize objects.As constructor is defined as a function and inside class function can have only two type either static or non static.My doubt is what constructor is ?
1.)As constructor is called without object so it must be static
Test test =new Test();//Test() is being called without object
so must be static
My doubt is if constructor is static method then how can we frequently used this inside
constructor
Test(){
System.out.println(this);
}
Does the output Test#12aw212 mean constructors are non-static?
Your second example hits the spot. this reference is available in the constructor, which means constructor is executed against some object - the one that is currently being created.
In principle when you create a new object (by using new operator), JVM will allocate some memory for it and then call a constructor on that newly created object. Also JVM makes sure that no other method is called before the constructor (that's what makes it special).
Actually, on machine level, constructor is a function with one special, implicit this parameter. This special parameter (passed by the runtime) makes the difference between object and static methods. In other words:
foo.bar(42);
is translated to:
bar(foo, 42);
where first parameter is named this. On the other hand static methods are called as-is:
Foo.bar(42);
translates to:
bar(42);
Foo here is just a namespace existing barely in the source code.
Constructors are non-static. Every method first parameter is implicit this (except static) and constructor is one of that.
Constructors are NOT static functions. When you do Test test =new Test(); a new Test object is created and then the constructor is called on that object (I mean this points to the newly created object).
The new keyword here is the trick. You're correct in noting that in general, if you're calling it without an object, a method is static. However in this special case (i.e., preceded by the new keyword) the compiler knows to call the constructor.
The new operator returns a reference to the object it created.
new Test(); // creates an instance.
The System.out.println(this); is called after the new operator has instantiated the object
Not static. Read about constructors http://www.javaworld.com/jw-10-2000/jw-1013-constructors.html.
Neither.
Methods can be divided into 2 types: static/non-static methods, aka class/instance methods.
But constructors are not methods.
When we talk about static class then it comes to our mind that methods are called with class name,But in case of constructor ,Constructor is initialized when object is created So this proves to be non-static.
Constructors are neither static (as called using class name) or non-static as executed while creating an object.
Static:
Temp t= new Temp();
The new operator creates memory in the heap area and passes it to the constructor as Temp(this) implicitly. It then initializes a non-static instance variable defined in a class called this to the local parameter variable this.
Below example is just for understanding the concept, if someone tries to compile it, it will give the compile-time error.
class Temp{
int a;
Temp this; //inserted by compiler.
Temp(Temp this){ //passed by compiler
this.this=this; // initialise this instance variable here.
this.a=10;//when we write only a=10; and all the non-static member access by this implicitly.
return this; // so that we can't return any value from constructor.
}
}
Constructor is static because:
It is helping to create object.
It is called without object.
Constructor is used to initialize the object and has the behavior of non-static methods,as non-static methods belong to objects so as constructor also and its invoked by the JVM to initialize the objects with the reference of object,created by new operator
I am a bit ashamed to ask that, being a Java programmer for years, but here goes:
Is there a difference between allocating objects during construction, and doing so directly when declaring the relevant field? That is, is there a difference between the following two:
public class MyClass{
MyObj obj=new MyObj();
}
AND
public class MyClass{
MyObj obj;
public MyClass() {
obj=new MyObj();
}
}
Of course, I assume this specific init's do not rely on outside parameters.
instance variable initialization done before constructor call
Its not good to do.
You can restrict user from call of const. if you want to perform certain operation before initialization.
Best Practice:
Don't initialize with the default values in declaration (null, false, 0, 0.0...).
Prefer initialization in declaration if you don't have a constructor parameter that changes the value of the field.
If the value of the field changes because of a constructor parameter put the >initialization in the constructors.
Be consistent in your practice. (the most important rule)
from here
No, there isn't. Except that if you add multiple constructors you'll have duplicate code.
An alternative is to use an initializer block
{
var = 1;
}
Reference: Initializing Fields
This question already has answers here:
Should I instantiate instance variables on declaration or in the constructor?
(15 answers)
Closed 9 years ago.
When I use Java based on my C++ knowledge, I love to initialize variable using the following way.
public class ME {
private int i;
public ME() {
this.i = 100;
}
}
After some time, I change the habit to
public class ME {
private int i = 100;
public ME() {
}
}
I came across others source code, some are using 1st convention, others are using 2nd convention.
May I know which convention do you all recommend, and why?
I find the second style (declaration + initialization in one go) superior. Reasons:
It makes it clear at a glance how the variable is initialized. Typically, when reading a program and coming across a variable, you'll first go to its declaration (often automatic in IDEs). With style 2, you see the default value right away. With style 1, you need to look at the constructor as well.
If you have more than one constructor, you don't have to repeat the initializations (and you cannot forget them).
Of course, if the initialization value is different in different constructors (or even calculated in the constructor), you must do it in the constructor.
I have the practice (habit) of almost always initializing in the contructor for two reasons, one in my opinion it adds to readablitiy (cleaner), and two there is more logic control in the constructor than in one line. Even if initially the instance variable doesn't require logic, having it in the constructor gives more flexibility to add logic in the future if needed.
As to the concern mentioned above about multiple constructors, that's easily solved by having one no-arg constructor that initializes all the instance variables that are initilized the same for all constructors and then each constructor calls this() at the first line. That solves your reduncancy issues.
I tend to use the second one to avoid a complicated constructor (or a useless one), also I don't really consider this as an initialization (even if it is an initialization), but more like giving a default value.
For example in your second snippet, you can remove the constructor and have a clearer code.
If you initialize in the top or in constructor it doesn't make much difference .But in some case initializing in constructor makes sense.
class String
{
char[] arr/*=char [20]*/; //Here initializing char[] over here will not make sense.
String()
{
this.arr=new char[0];
}
String(char[] arr)
{
this.arr=arr;
}
}
So depending on the situation sometime you will have to initialize in the top and sometimes in a constructor.
FYI other option's for initialization without using a constructor :
class Foo
{
int i;
static int k;
//instance initializer block
{
//run's every time a new object is created
i=20;
}
//static initializer block
static{
//run's only one time when the class is loaded
k=18;
}
}
The only problem I see with the first method is if you are planning to add more constructors. Then you will be repeating code and maintainability would suffer.
I recommend initializing variables in constructors. That's why they exist: to ensure your objects are constructed (initialized) properly.
Either way will work, and it's a matter of style, but I prefer constructors for member initialization.
Both the options can be correct depending on your situation.
A very simple example would be: If you have multiple constructors all of which initialize the variable the same way(int x=2 for each one of them). It makes sense to initialize the variable at declaration to avoid redundancy.
It also makes sense to consider final variables in such a situation. If you know what value a final variable will have at declaration, it makes sense to initialize it outside the constructors. However, if you want the users of your class to initialize the final variable through a constructor, delay the initialization until the constructor.
One thing, regardless of how you initialize the field, use of the final qualifier, if possible, will ensure the visibility of the field's value in a multi-threaded environment.
I think both are correct programming wise,
But i think your first option is more correct in an object oriented way, because in the constructor is when the object is created, and it is when the variable should initialized.
I think it is the "by the book" convention, but it is open for discussion.
Wikipedia
It can depend on what your are initialising, for example you cannot just use field initialisation if a checked exception is involved. For example, the following:
public class Foo {
FileInputStream fis = new FileInputStream("/tmp"); // throws FileNotFoundException
}
Will cause a compile-time error unless you also include a constructor declaring that checked exception, or extend a superclass which does, e.g.:
public Foo() throws FileNotFoundException {}
I would say, it depends on the default. For example
public Bar
{
ArrayList<Foo> foos;
}
I would make a new ArrayList outside of the constructor, if I always assume foos can not be null. If Bar is a valid object, not caring if foos is null or not, I would put it in the constructor.
You might disagree and say that it's the constructors job to put the object in a valid state. However, if clearly all the constructors should do exactly the same thing(initialize foos), why duplicate that code?