Should I Instantiate Instance Variables on Declaration or in the Constructor

Should I instantiate instance variables on declaration or in the constructor?


  • There is no difference - the instance variable initialization is actually put in the constructor(s) by the compiler.
  • The first variant is more readable.
  • You can't have exception handling with the first variant.
  • There is additionally the initialization block, which is as well put in the constructor(s) by the compiler:

    {
    a = new A();
    }

Check Sun's explanation and advice

From this tutorial:

Field declarations, however, are not part of any method, so they cannot be executed as statements are. Instead, the Java compiler generates instance-field initialization code automatically and puts it in the constructor or constructors for the class. The initialization code is inserted into a constructor in the order it appears in the source code, which means that a field initializer can use the initial values of fields declared before it.

Additionally, you might want to lazily initialize your field. In cases when initializing a field is an expensive operation, you may initialize it as soon as it is needed:

ExpensiveObject o;

public ExpensiveObject getExpensiveObject() {
if (o == null) {
o = new ExpensiveObject();
}
return o;
}

And ultimately (as pointed out by Bill), for the sake of dependency management, it is better to avoid using the new operator anywhere within your class. Instead, using Dependency Injection is preferable - i.e. letting someone else (another class/framework) instantiate and inject the dependencies in your class.

Should I initialize variable within constructor or outside constructor

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.

Initilizing outside constructor vs inside

There is no difference between the two methods. If you were working in an activity or fragment class then it would be best to initialize a variable inside onCreate. The only advantage of initializing it outside constructor in such a scenario would be if other functions need to load before onCreate is called.

But in a situation of a class, then there is no difference is by the preference of the coder.

Why should I use constructor if I can initialize instance variable another way


You should use me because I will help you keep your initializations in one place. Because it will help you other colleagues to know where to expect initializations and not miss one if they're scattered aroudn the code.

Initializing instance variables via Get & Set vs Constructor

If you use a constructor to initialize a global variable then you can do it only at the time when you will create an object.Think of a case where you might to change the value of a variable very often in that case you need not to create a new object to do that just call the getter and setter methods and thy will do the job for you .
Constructors will automatically do the job only once when you will declare it but getter and setter method could do that job again and again as and when you need.

Instance Variable Declaration and instantiation

They are so similar that for basic programming they could be considered equivalent. The most obvious thing you might notice is when you add another constructor to PersonDirectory, like so:

public class PersonDirectory {
private ArrayList<Person> persons;
private DirectoryAdmin admin;
public PersonDirectory() {
persons = new ArrayList<Person>();
}
public PersonDirectory(DirectoryAdmin initialAdmin) {
admin = initialAdmin;
}
}

If you utilize this second constructor, you would find that persons is null after constructing PersonDirectory. This is because Java does not run other constructors for you automatically. You could fix the problem by adding an explicit call to this(), which runs also the constructor that matches the signature of the this call.

public class PersonDirectory {
private ArrayList<Person> persons;
private DirectoryAdmin admin;
public PersonDirectory() {
persons = new ArrayList<Person>();
}
public PersonDirectory(DirectoryAdmin initialAdmin) {
this();
admin = initialAdmin;
}
}

But often times programmers forget to add the call to this(); and may find out too late that persons has been left null because one of their constructors was written carelessly.

If you instead write the initialization inline with the declaration, the initialization is run regardless of which PersonDirectory constructor you call, and so could be considered slightly less error-prone.

public class PersonDirectory {
private ArrayList<Person> persons = new ArrayList<Person>();
private DirectoryAdmin admin;
public PersonDirectory() {
}
public PersonDirectory(DirectoryAdmin initialAdmin) {
// don't have to worry about forgetting to call this();
admin = initialAdmin;
}
}

There are, however, reasons to sometimes prefer initialization in the constructor. For example, it can give more control to subclasses and their constructors.

It is a good practice to declare your member variables final whenever possible. This way the compiler can remind you if you've written a constructor that leaves some fields uninitialized.

Inline initialization statements always run before the class's constructor(s).

Java instance variable initialization inside and outside constructor confusion


Precedence

In your case the int j happens first and defaults to 0, then gets reassigned to 5 when the constructor is called on to create a new instance.

j only gets re-assigned when the constructor runs. Instance members get initialized first when you assign them something outside the constructor.

Order of Execution

Each line of code gets executed in the order it appears. The declarations happen before the constructor always, in the order they are listed in the code.

Deterministic and Predictable

You should only initialize instance members in a single place, inside a single constructor.

Relying on defaults leads to hard to track down bugs, and makes testing a nightmare, but a instance member that is unassigned will stand out like a sore thumb to the IDE, the compiler and at runtime. Unfortunately for primitives like int they default to 0 which might not be what you want/need.

A better design is:

 private final int j;

public Foo(final int j) { this.j = j; }

This keeps the j from getting assigned anything on initialization and you never have to worry about it changing.



Related Topics



Leave a reply



Submit