So I've been brushing up on my Java skills as of late and have found a few bits of functionality that I didn't know about previously. Static and Instance Initializers are two such techniques.
My question is when would one use an initializer instead of including the code in a constructor? I've thought of a couple obvious possibilities:
static/instance initializers can be used to set the value of "final" static/instance variables whereas a constructor cannot
static initializers can be used to set the value of any static variables in a class, which should be more efficient than having an "if (someStaticVar == null) // do stuff" block of code at the start of each constructor
Both of these cases assume that the code required to set these variables is more complex than simply "var = value", as otherwise there wouldn't seem to be any reason to use an initializer instead of simply setting the value when declaring the variable.
However, while these aren't trivial gains (especially the ability to set a final variable), it does seem that there are a rather limited number of situations in which an initializer should be used.
One can certainly use an initializer for a lot of what is done in a constructor, but I don't really see the reason to do so. Even if all constructors for a class share a large amount of code, the use of a private initialize() function seems to make more sense to me than using an initializer because it doesn't lock you into having that code run when writing a new constructor.
Am I missing something? Are there a number of other situations in which an initializer should be used? Or is it really just a rather limited tool to be used in very specific situations?
Static initializers are useful as cletus mentioned and I use them in the same manner. If you have a static variable that is to be initialized when the class is loaded, then a static initializer is the way to go, especially as it allows you to do a complex initialization and still have the static variable be final. This is a big win.
I find "if (someStaticVar == null) // do stuff" to be messy and error prone. If it is initialized statically and declared final, then you avoid the possibility of it being null.
However, I'm confused when you say:
static/instance initializers can be used to set the value of "final"
static/instance variables whereas a constructor cannot
I assume you are saying both:
static initializers can be used to set the value of "final" static variables whereas a constructor cannot
instance initializers can be used to set the value of "final" instance variables whereas a constructor cannot
and you are correct on the first point, wrong on the second. You can, for example, do this:
class MyClass {
private final int counter;
public MyClass(final int counter) {
this.counter = counter;
}
}
Also, when a lot of code is shared between constructors, one of the best ways to handle this is to chain constructors, providing the default values. This makes is pretty clear what is being done:
class MyClass {
private final int counter;
public MyClass() {
this(0);
}
public MyClass(final int counter) {
this.counter = counter;
}
}
Anonymous inner classes can't have a constructor (as they're anonymous), so they're a pretty natural fit for instance initializers.
I most often use static initializer blocks for setting up final static data, especially collections. For example:
public class Deck {
private final static List<String> SUITS;
static {
List<String> list = new ArrayList<String>();
list.add("Clubs");
list.add("Spades");
list.add("Hearts");
list.add("Diamonds");
SUITS = Collections.unmodifiableList(list);
}
...
}
Now this example can be done with a single line of code:
private final static List<String> SUITS =
Collections.unmodifiableList(
Arrays.asList("Clubs", "Spades", "Hearts", "Diamonds")
);
but the static version can be far neater, particularly when the items are non-trivial to initialize.
A naive implementation may also not create an unmodifiable list, which is a potential mistake. The above creates an immutable data structure that you can happily return from public methods and so on.
Just to add to some already excellent points here. The static initializer is thread safe. It is executed when the class is loaded, and thus makes for simpler static data initialization than using a constructor, in which you would need a synchronized block to check if the static data is initialized and then actually initialize it.
public class MyClass {
static private Properties propTable;
static
{
try
{
propTable.load(new FileInputStream("/data/user.prop"));
}
catch (Exception e)
{
propTable.put("user", System.getProperty("user"));
propTable.put("password", System.getProperty("password"));
}
}
versus
public class MyClass
{
public MyClass()
{
synchronized (MyClass.class)
{
if (propTable == null)
{
try
{
propTable.load(new FileInputStream("/data/user.prop"));
}
catch (Exception e)
{
propTable.put("user", System.getProperty("user"));
propTable.put("password", System.getProperty("password"));
}
}
}
}
Don't forget, you now have to synchronize at the class, not instance level. This incurs a cost for every instance constructed instead of a one time cost when the class is loaded. Plus, it's ugly ;-)
I read a whole article looking for an answer to the init order of initializers vs. their constructors. I didn't find it, so I wrote some code to check my understanding. I thought I would add this little demonstration as a comment. To test your understanding, see if you can predict the answer before reading it at the bottom.
/**
* Demonstrate order of initialization in Java.
* #author Daniel S. Wilkerson
*/
public class CtorOrder {
public static void main(String[] args) {
B a = new B();
}
}
class A {
A() {
System.out.println("A ctor");
}
}
class B extends A {
int x = initX();
int initX() {
System.out.println("B initX");
return 1;
}
B() {
super();
System.out.println("B ctor");
}
}
Output:
java CtorOrder
A ctor
B initX
B ctor
A static initializer is the equivalent of a constructor in the static context. You will certainly see that more often than an instance initializer. Sometimes you need to run code to set up the static environment.
In general, an instance initalizer is best for anonymous inner classes. Take a look at JMock's cookbook to see an innovative way to use it to make code more readable.
Sometimes, if you have some logic which is complicated to chain across constructors (say you are subclassing and you can't call this() because you need to call super()), you could avoid duplication by doing the common stuff in the instance initalizer. Instance initalizers are so rare, though, that they are a surprising syntax to many, so I avoid them and would rather make my class concrete and not anonymous if I need the constructor behavior.
JMock is an exception, because that is how the framework is intended to be used.
There is one important aspect that you have to consider in your choice:
Initializer blocks are members of the class/object, while constructors are not.
This is important when considering extension/subclassing:
Initializers are inherited by subclasses. (Though, can be shadowed)
This means it is basically guaranteed that subclasses are initialized as intended by the parent class.
Constructors are not inherited, though. (They only call super() [i.e. no parameters] implicitly or you have to make a specific super(...) call manually.)
This means it is possible that a implicit or exclicit super(...) call might not initialize the subclass as intended by the parent class.
Consider this example of an initializer block:
class ParentWithInitializer {
protected String aFieldToInitialize;
{
aFieldToInitialize = "init";
System.out.println("initializing in initializer block of: "
+ this.getClass().getSimpleName());
}
}
class ChildOfParentWithInitializer extends ParentWithInitializer{
public static void main(String... args){
System.out.println(new ChildOfParentWithInitializer().aFieldToInitialize);
}
}
output:
initializing in initializer block of: ChildOfParentWithInitializer
init
-> No matter what constructors the subclass implements, the field will be initialized.
Now consider this example with constructors:
class ParentWithConstructor {
protected String aFieldToInitialize;
// different constructors initialize the value differently:
ParentWithConstructor(){
//init a null object
aFieldToInitialize = null;
System.out.println("Constructor of "
+ this.getClass().getSimpleName() + " inits to null");
}
ParentWithConstructor(String... params) {
//init all fields to intended values
aFieldToInitialize = "intended init Value";
System.out.println("initializing in parameterized constructor of:"
+ this.getClass().getSimpleName());
}
}
class ChildOfParentWithConstructor extends ParentWithConstructor{
public static void main (String... args){
System.out.println(new ChildOfParentWithConstructor().aFieldToInitialize);
}
}
output:
Constructor of ChildOfParentWithConstructor inits to null
null
-> This will initialize the field to null by default, even though it might not be the result you wanted.
I would also like to add one point along with all the above fabulous answers . When we load a driver in JDBC using Class.forName("") the the Class loading happens and the static initializer of the Driver class gets fired and the code inside it registers Driver to Driver Manager. This is one of the significant use of static code block.
As you mentioned, it's not useful in a lot of cases and as with any less-used syntax, you probably want to avoid it just to stop the next person looking at your code from spending the 30 seconds to pull it out of the vaults.
On the other hand, it is the only way to do a few things (I think you pretty much covered those).
Static variables themselves should be somewhat avoided anyway--not always, but if you use a lot of them, or you use a lot in one class, you might find different approaches, your future self will thank you.
Note that one big issue with static initializers that perform some side effects, is that they cannot be mocked in unit tests.
I've seen libraries do that, and it's a big pain.
So it's best to keep those static initializers pure only.
Related
Is there any advantage for either approach?
Example 1:
class A {
B b = new B();
}
Example 2:
class A {
B b;
A() {
b = new B();
}
}
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.
Another option would be to use Dependency Injection.
class A{
B b;
A(B b) {
this.b = b;
}
}
This removes the responsibility of creating the B object from the constructor of A. This will make your code more testable and easier to maintain in the long run. The idea is to reduce the coupling between the two classes A and B. A benefit that this gives you is that you can now pass any object that extends B (or implements B if it is an interface) to A's constructor and it will work. One disadvantage is that you give up encapsulation of the B object, so it is exposed to the caller of the A constructor. You'll have to consider if the benefits are worth this trade-off, but in many cases they are.
I got burned in an interesting way today:
class MyClass extends FooClass {
String a = null;
public MyClass() {
super(); // Superclass calls init();
}
#Override
protected void init() {
super.init();
if (something)
a = getStringYadaYada();
}
}
See the mistake? It turns out that the a = null initializer gets called after the superclass constructor is called. Since the superclass constructor calls init(), the initialization of a is followed by the a = null initialization.
my personal "rule" (hardly ever broken) is to:
declare all variables at the start of
a block
make all variables final unless they
cannot be
declare one variable per line
never initialize a variable where
declared
only initialize something in a
constructor when it needs data from
the constructor to do the
initialization
So I would have code like:
public class X
{
public static final int USED_AS_A_CASE_LABEL = 1; // only exception - the compiler makes me
private static final int A;
private final int b;
private int c;
static
{
A = 42;
}
{
b = 7;
}
public X(final int val)
{
c = val;
}
public void foo(final boolean f)
{
final int d;
final int e;
d = 7;
// I will eat my own eyes before using ?: - personal taste.
if(f)
{
e = 1;
}
else
{
e = 2;
}
}
}
This way I am always 100% certain where to look for variables declarations (at the start of a block), and their assignments (as soon as it makes sense after the declaration). This winds up potentially being more efficient as well since you never initialize a variable with a value that is not used (for example declare and init vars and then throw an exception before half of those vars needed to have a value). You also do not wind up doing pointless initialization (like int i = 0; and then later on, before "i" is used, do i = 5;.
I value consistency very much, so following this "rule" is something I do all the time, and it makes it much easier to work with the code since you don't have to hunt around to find things.
Your mileage may vary.
Example 2 is less flexible. If you add another constructor, you need to remember to instantiate the field in that constructor as well. Just instantiate the field directly, or introduce lazy loading somewhere in a getter.
If instantiation requires more than just a simple new, use an initializer block. This will be run regardless of the constructor used. E.g.
public class A {
private Properties properties;
{
try {
properties = new Properties();
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("file.properties"));
} catch (IOException e) {
throw new ConfigurationException("Failed to load properties file.", e); // It's a subclass of RuntimeException.
}
}
// ...
}
Using either dependency injection or lazy initialization is always preferable, as already explained thoroughly in other answers.
When you don't want or can't use those patterns, and for primitive data types, there are three compelling reasons that I can think of why it's preferable to initialize the class attributes outside the constructor:
avoided repetition = if you have more than one constructor, or when you will need to add more, you won't have to repeat the initialization over and over in all the constructors bodies;
improved readability = you can easily tell with a glance which variables will have to be initialized from outside the class;
reduced lines of code = for every initialization done at the declaration there will be a line less in the constructor.
I take it is almost just a matter of taste, as long as initialization is simple and doesn't need any logic.
The constructor approach is a bit more fragile if you don't use an initializer block, because if you later on add a second constructor and forget to initialize b there, you'll get a null b only when using that last constructor.
See http://java.sun.com/docs/books/tutorial/java/javaOO/initial.html for more details about initialization in Java (and for explanations on initalizer blocks and other not well known initialization features).
I've not seen the following in the replies:
A possible advantage of having the initialisation at the time of declaration might be with nowadays IDE's where you can very easily jump to the declaration of a variable (mostly
Ctrl-<hover_over_the_variable>-<left_mouse_click>) from anywhere in your code. You then immediately see the value of that variable. Otherwise, you have to "search" for the place where the initialisation is done (mostly: constructor).
This advantage is of course secondary to all other logical reasonings, but for some people that "feature" might be more important.
Both of the methods are acceptable. Note that in the latter case b=new B() may not get initialized if there is another constructor present. Think of initializer code outside constructor as a common constructor and the code is executed.
I think Example 2 is preferable. I think the best practice is to declare outside the constructor and initialize in the constructor.
The second is an example of lazy initialization. First one is more simple initialization, they are essentially same.
There is one more subtle reason to initialize outside the constructor that no one has mentioned before (very specific I must say). If you are using UML tools to generate class diagrams from the code (reverse engineering), most of the tools I believe will note the initialization of Example 1 and will transfer it to a diagram (if you prefer it to show the initial values, like I do). They will not take these initial values from Example 2. Again, this is a very specific reason - if you are working with UML tools, but once I learned that, I am trying to take all my default values outside of constructor unless, as was mentioned before, there is an issue of possible exception throwing or complicated logic.
The second option is preferable as allows to use different logic in ctors for class instantiation and use ctors chaining. E.g.
class A {
int b;
// secondary ctor
A(String b) {
this(Integer.valueOf(b));
}
// primary ctor
A(int b) {
this.b = b;
}
}
So the second options is more flexible.
It's quite different actually:
The declaration happens before construction. So say if one has initialized the variable (b in this case) at both the places, the constructor's initialization will replace the one done at the class level.
So declare variables at the class level, initialize them in the constructor.
class MyClass extends FooClass {
String a = null;
public MyClass() {
super(); // Superclass calls init();
}
#Override
protected void init() {
super.init();
if (something)
a = getStringYadaYada();
}
}
Regarding the above,
String a = null;
null init could be avoided since anyway it's the default.
However, if you were to need another default value,
then, because of the uncontrolled initialization order,
I would fix as follow:
class MyClass extends FooClass
{
String a;
{
if( a==null ) a="my custom default value";
}
...
How and where should we use a Static modifier for:
1. Field and
2. Method?
For example in java.lang.Math class, the fields methods like abs(), atan(), cos() etc are static, i.e. they can be accessed as: Math.abs()
But why is it a good practice?
Say, I don't keep it static and create an object of the class and access it, which anyways I can, I will just get a warning that, you are trying to access a static method in a non static way (as pointed out by #duffymo, not in case of Math class).
UPDATE 1:
So, utility method, should be static, i.e. whose work is only dependent on the method parameters. So, for example, can the method updateString(String inputQuery, String highlightDoc) should have been a static method in this question?
You can think of a 'static' method or field as if it were declared outside the class definition. In other words
There is only one 'copy' of a static field/method.
Static fields/methods cannot access non-static fields/methods.
There are several instances where you would want to make something static.
The canonical example for a field is to make a static integer field which keeps a count across all instances (objects) of a class. Additionally, singleton objects, for example, also typically employ the static modifier.
Similarly, static methods can be used to perform 'utility' jobs for which all the required dependencies are passed in as parameters to the method - you cannot reference the 'this' keyword inside of a static method.
In C#, you can also have static classes which, as you might guess, contain only static members:
public static class MyContainer
{
private static int _myStatic;
public static void PrintMe(string someString)
{
Console.Out.WriteLine(someString);
_myStatic++;
}
public static int PrintedInstances()
{
return _myStatic;
}
}
Static uses less memory since it exists only once per Classloader.
To have methods static may save some time, beacuse you do not have to create an object first so you can call a function. You can/should use static methods when they stand pretty much on their own (ie. Math.abs(X) - there really is no object the function needs.) Basically its a convenience thing (at least as far as I see it - others might and will disagree :P)
Static fields should really be used with caution. There are quite a few patterns that need static fields... but the basics first:
a static field exists only once. So if you have a simple class (kinda pseudocode):
class Simple {
static int a;
int b;
}
and now you make objects with:
Simple myA = new Simple();
Simple myB = new Simple();
myA.a = 1;
myA.b = 2;
myB.a = 3;
myB.b = 4;
System.out.println(myA.a + myA.b + myB.a + myB.b);
you will get 3234 - because by setting myB.a you actually overwrite myA.a as well because a is static. It exists in one place in memory.
You normally want to avoid this because really weird things might happen. But if you google for example for Factory Pattern you will see that there are actually quite useful uses for this behaviour.
Hope that clears it up a little.
Try taking a look at this post, it also gives some examples of when to and when not to use static and final modifiers.
Most of the posts above are similar, but this post might offer some other insight. When to use Static Modifiers
Usually when the method only depends on the function parameters and not on the internal state of the object it's a static method (with singletone being the only exception). I can't imagine where static fields are really used (they're the same as global variables which should be avoided).
Like in your example the math functions only depend on the parameters.
For a field you should keep it static if you want all instances of a given class to have access to its value. For example if I have
public static int age = 25;
Then any instance of the class can get or set the value of age with all pointing to the same value. If you do make something static you run the risk of having two instances overwriting each others values and possibly causing problems.
The reason to create static methods is mostly for utility function where all the required data for the method is passed in and you do not want to take the over head of creating an instance of the class each time you want to call the method.
You can't instantiate an instance of java.lang.Math; there isn't a public constructor.
Try it:
public class MathTest
{
public static void main(String [] args)
{
Math math = new Math();
System.out.println("math.sqrt(2) = " + math.sqrt(2));
}
}
Here's what you'll get:
C:\Documents and Settings\Michael\My Documents\MathTest.java:5: Math() has private access in java.lang.Math
Math math = new Math();
^
1 error
Tool completed with exit code 1
class StaticModifier
{
{
System.out.println("Within init block");//third
}
public StaticModifier()
{
System.out.println("Within Constructor");//fourth
}
public static void main(String arr[])
{
System.out.println("Within Main:");//second
//StaticModifier obj=new StaticModifier();
}
static
{
System.out.print("Within static block");//first
}
}
If I create an instance of a class in Java, why is it preferable to call a static method of that same class statically, rather than using this.method()?
I get a warning from Eclipse when I try to call static method staticMethod() from within the custom class's constructor via this.staticMethod().
public MyClass() { this.staticMethod(); }
vs
public MyClass() { MyClass.staticMethod(); }
Can anyone explain why this is a bad thing to do? It seems to me like the compiler should already have allocated an instance of the object, so statically allocating memory would be unneeded overhead.
EDIT:
The gist of what I'm hearing is that this is bad practice mainly because of readability, and understandably so. What I was really trying to ask (albeit not very clearly) was what differences there are at 'compilation', if any, between calling MyClass.staticMethod() or this.staticMethod().
Static methods are not tied to an instance of the class, so it makes less sense to call it from a this than to call it from Class.staticMethod(), much more readable too.
MyClass.staticMethod() makes it clear that you are calling a static (non-overrideable) method.
this.staticMethod() misleads the reader into thinking that it is an instance method.
staticMethod() is also on the misleading side (though I normally do it that way).
If you think of people reading your code as unfamiliar with it you tend to try to make the code clearer, and this is a case where the code is clearer by having ClassName.method instead of instance.method.
In addition to the other answers which have mentioned making it clear you're using a static method, also note that static methods are not polymorphic, so being explicit with the class name can remove any confusion as to which method is going to be called.
In the code below, it's not entirely obvious that b.test() is going to return "A" if you're expecting the polymorphism of a non-static method:
public class TestStaticOverride
{
public static void main( String[] args )
{
A b = new B();
System.out.println( "Calling b.test(): " + b.test() );
}
private static class A
{
public static String test() { return "A"; }
}
private static class B extends A
{
public static String test() { return "B"; }
}
}
If you change the code to B b = new B(); it will print out "B".
(Whether it's ever a good idea to "override" static methods is probably a discussion for another day...)
Static methods are really not part of your instance - and it will not be able to access any of your instance variables anyway, so I would dare thinking it doesn't make a lot of sense calling it from the constructor.
If your need to initialize static objects use
private static List l = new ArrayList(); static { l.add("something"); }
If you still need to call it its perfectly legal to call local static methods without prefixing your local class name, like this (no eclipse warning)
public MyClass() { staticMethod(); }
Because this. normally reference to instance methods, therefore, it's a bad idea to do that.
Is there any advantage for either approach?
Example 1:
class A {
B b = new B();
}
Example 2:
class A {
B b;
A() {
b = new B();
}
}
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.
Another option would be to use Dependency Injection.
class A{
B b;
A(B b) {
this.b = b;
}
}
This removes the responsibility of creating the B object from the constructor of A. This will make your code more testable and easier to maintain in the long run. The idea is to reduce the coupling between the two classes A and B. A benefit that this gives you is that you can now pass any object that extends B (or implements B if it is an interface) to A's constructor and it will work. One disadvantage is that you give up encapsulation of the B object, so it is exposed to the caller of the A constructor. You'll have to consider if the benefits are worth this trade-off, but in many cases they are.
I got burned in an interesting way today:
class MyClass extends FooClass {
String a = null;
public MyClass() {
super(); // Superclass calls init();
}
#Override
protected void init() {
super.init();
if (something)
a = getStringYadaYada();
}
}
See the mistake? It turns out that the a = null initializer gets called after the superclass constructor is called. Since the superclass constructor calls init(), the initialization of a is followed by the a = null initialization.
my personal "rule" (hardly ever broken) is to:
declare all variables at the start of
a block
make all variables final unless they
cannot be
declare one variable per line
never initialize a variable where
declared
only initialize something in a
constructor when it needs data from
the constructor to do the
initialization
So I would have code like:
public class X
{
public static final int USED_AS_A_CASE_LABEL = 1; // only exception - the compiler makes me
private static final int A;
private final int b;
private int c;
static
{
A = 42;
}
{
b = 7;
}
public X(final int val)
{
c = val;
}
public void foo(final boolean f)
{
final int d;
final int e;
d = 7;
// I will eat my own eyes before using ?: - personal taste.
if(f)
{
e = 1;
}
else
{
e = 2;
}
}
}
This way I am always 100% certain where to look for variables declarations (at the start of a block), and their assignments (as soon as it makes sense after the declaration). This winds up potentially being more efficient as well since you never initialize a variable with a value that is not used (for example declare and init vars and then throw an exception before half of those vars needed to have a value). You also do not wind up doing pointless initialization (like int i = 0; and then later on, before "i" is used, do i = 5;.
I value consistency very much, so following this "rule" is something I do all the time, and it makes it much easier to work with the code since you don't have to hunt around to find things.
Your mileage may vary.
Example 2 is less flexible. If you add another constructor, you need to remember to instantiate the field in that constructor as well. Just instantiate the field directly, or introduce lazy loading somewhere in a getter.
If instantiation requires more than just a simple new, use an initializer block. This will be run regardless of the constructor used. E.g.
public class A {
private Properties properties;
{
try {
properties = new Properties();
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("file.properties"));
} catch (IOException e) {
throw new ConfigurationException("Failed to load properties file.", e); // It's a subclass of RuntimeException.
}
}
// ...
}
Using either dependency injection or lazy initialization is always preferable, as already explained thoroughly in other answers.
When you don't want or can't use those patterns, and for primitive data types, there are three compelling reasons that I can think of why it's preferable to initialize the class attributes outside the constructor:
avoided repetition = if you have more than one constructor, or when you will need to add more, you won't have to repeat the initialization over and over in all the constructors bodies;
improved readability = you can easily tell with a glance which variables will have to be initialized from outside the class;
reduced lines of code = for every initialization done at the declaration there will be a line less in the constructor.
I take it is almost just a matter of taste, as long as initialization is simple and doesn't need any logic.
The constructor approach is a bit more fragile if you don't use an initializer block, because if you later on add a second constructor and forget to initialize b there, you'll get a null b only when using that last constructor.
See http://java.sun.com/docs/books/tutorial/java/javaOO/initial.html for more details about initialization in Java (and for explanations on initalizer blocks and other not well known initialization features).
I've not seen the following in the replies:
A possible advantage of having the initialisation at the time of declaration might be with nowadays IDE's where you can very easily jump to the declaration of a variable (mostly
Ctrl-<hover_over_the_variable>-<left_mouse_click>) from anywhere in your code. You then immediately see the value of that variable. Otherwise, you have to "search" for the place where the initialisation is done (mostly: constructor).
This advantage is of course secondary to all other logical reasonings, but for some people that "feature" might be more important.
Both of the methods are acceptable. Note that in the latter case b=new B() may not get initialized if there is another constructor present. Think of initializer code outside constructor as a common constructor and the code is executed.
I think Example 2 is preferable. I think the best practice is to declare outside the constructor and initialize in the constructor.
The second is an example of lazy initialization. First one is more simple initialization, they are essentially same.
There is one more subtle reason to initialize outside the constructor that no one has mentioned before (very specific I must say). If you are using UML tools to generate class diagrams from the code (reverse engineering), most of the tools I believe will note the initialization of Example 1 and will transfer it to a diagram (if you prefer it to show the initial values, like I do). They will not take these initial values from Example 2. Again, this is a very specific reason - if you are working with UML tools, but once I learned that, I am trying to take all my default values outside of constructor unless, as was mentioned before, there is an issue of possible exception throwing or complicated logic.
The second option is preferable as allows to use different logic in ctors for class instantiation and use ctors chaining. E.g.
class A {
int b;
// secondary ctor
A(String b) {
this(Integer.valueOf(b));
}
// primary ctor
A(int b) {
this.b = b;
}
}
So the second options is more flexible.
It's quite different actually:
The declaration happens before construction. So say if one has initialized the variable (b in this case) at both the places, the constructor's initialization will replace the one done at the class level.
So declare variables at the class level, initialize them in the constructor.
class MyClass extends FooClass {
String a = null;
public MyClass() {
super(); // Superclass calls init();
}
#Override
protected void init() {
super.init();
if (something)
a = getStringYadaYada();
}
}
Regarding the above,
String a = null;
null init could be avoided since anyway it's the default.
However, if you were to need another default value,
then, because of the uncontrolled initialization order,
I would fix as follow:
class MyClass extends FooClass
{
String a;
{
if( a==null ) a="my custom default value";
}
...
In other words, why would you need an instance initializer? What difference or advantage do you have in writing a instance initializer over a constructor?
This seems to explain it well:
Instance initializers are a useful alternative to instance variable
initializers whenever:
initializer code must catch exceptions, or
perform fancy calculations that can't be expressed with an instance variable initializer. You could, of course, always write such code in
constructors.
But in a class that had multiple constructors, you would have to repeat the code in each constructor. With an instance initializer, you
can just write the code once, and it will be executed no matter what
constructor is used to create the object. Instance initializers are
also useful in anonymous inner classes, which can't declare any
constructors at all.
From: JavaWorld Object initialization in Java.
In terms of object lifecycle, there is no difference. Both are invoked at construction time, and logically the initializer block can be considered part of construction.
Semantically, an initializer is a nice tool to have for several reasons:
the initializer can improve code readability by keeping the initialization logic next to the variable being initialized:
public class Universe {
public int theAnswer;
{
int SIX = 6;
int NINE = 7;
theAnswer = SIX * NINE;
}
// a bunch of other vars
}
vs
public class Universe {
public int theAnswer;
// a bunch of other vars
public Universe() {
int SIX = 6;
int NINE = 7;
theAnswer = SIX * NINE;
// other constructor logic
}
}
Initializers are invoked regardless
of which constructor is used.
Initializers can be used in anonymous
inner classes, where constructors
can't.
When you have many constructors and want some common code to be executed for each constructor you can use instance initializer.As it is called for all constructors.
I would avoid the instance initializer idiom in general - the only real advantage it gives over variable initializers is exception handling.
And since an init method (callable from constructor) can also do exception handling and also centralizes constructor setup code, but has the advantage that it can operate on constructor parameter values, I'd say that the instance initializer is redundant, and therefore to be avoided.
The real advantage of instance initializers over constructors is seen when we use an anonymous inner class.
Anonymous inner classes can't have a constructor (as they're anonymous), so they're a pretty natural fit for instance initializers.
At the time of object creation, if we want to perform initialise of instance variables, then we should go for Constructor, other than initialisation activity if we want to perform any activity at the time of object creation then we should go for instance block.
We can't replace constructor with instance block because constructor can take argument but instance block can't take arguments.
We can't replace instance block wih constructor because a class can contain more than one constructor. If we want to replace instance block with constructor then in every constructor we have to write instance block code because at runtime which constructor will be called we can't expect, this will unnecesarily increase duplicate code.
Example :
class MyClass{
static int object_count = 0;
MyClass(){
object_count++;
}
MyClass(int i){
object_count++;
}
void getCount() {
System.out.println(object_count);
}
public static void main(String... args) {
MyClass one = new MyClass();
MyClass two = new MyClass(2);
two.getCount();
}
}
Output : 2
class MyClass{
static int object_count = 0;
{
object_count++;
}
MyClass(){
}
MyClass(int i){
}
void getCount() {
System.out.println(object_count);
}
public static void main(String... args) {
MyClass one = new MyClass();
MyClass two = new MyClass(2);
two.getCount();
}
}
Output : 2
Initializer is way to share code between constructors and it make code more readable if initializer is used with variable declaration.
The Java compiler copies initializer blocks into every constructor. Therefore, this approach can be used to share a block of code between multiple constructors.
Oracle documentation