views:

377

answers:

8

Hi

I have doubt in instance variable initialization in java.I have seen different developers initializing varibles differently.In the below sample codes what is better way.Do we have any advantage of initializing variables inside the constructor? .. Example 1 code is easy to read.Can anyone clarify this.....

Example 1:

class A {
  B b=new B();
}

Example 2:

class A{

 B b;

 A(){
  b=new B();
 }

}
A: 

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.

Chandra Patni
A: 

I think Example 2 is preferable. I think the best practice is to declare outside the constructor and initialize in the constructor.

jkeesh
A: 

The second is an example of lazy initialization. First one is more simple initialization, they are essentially same.

fastcodejava
+3  A: 

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).

Vinko Vrsalovic
thats why you have DI and @Required :)
Sujoy
Yes. I was only describing the dufferences between OP's two examples.
Vinko Vrsalovic
+10  A: 
  • 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.

Bozho
This answer now covers everything. Good job :)
Vinko Vrsalovic
+4  A: 

I would hesitate to use either of those methods, although your example 2 is slightly more preferable. Instead I would use:

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. This is one very simple example of Dependency Injection. 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 to A's constructor and it will work.

Bill the Lizard
On the other hand, it increases coupling in the sense that now you've made the link between `A` and `B` more visible. Previously, the use of `B` was an internal matter of `A`, and if it turns out that a better design is not to use `B`, your suggestion is harder to change.
jk
the coupling is there anyway - A needs B. But instantiating it inside the class means "A needs _exactly this B_ ", while DI allows for a number of differnt B's to be used.
Bozho
`A` needs `B` *now* in *this* design, and my point was about if that situation changes.
jk
@jk: If you separate object creation from business logic everywhere - specifically where A is created - by using DI and Factory classes, it isn't hard to change at all. It only needs to change in one place, the Factory that creates A objects. If you're consistent about it, it isn't hard to grasp at all. I think the benefits outweigh the costs. The coupling is reduced, and the overall design is eaier to test and maintain.
Bill the Lizard
+3  A: 

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;
        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.

TofuBeer
oh come on - what on earth was the down vote for?!
TofuBeer
it might have been for "never initialize a variable where declared" (though it wasn't me). Or the curly-bracket-on-new-line, which is thought to be a C/C++ idiom. Anyway, one upvote from me to compensate ;)
Bozho
I'd rather people down vote for a technical reason than an aesthetic one (the { } placement, or the non-required usage of them). If people down vote they should at least say what they think is wrong with the answer... there is nothing technically wrong, and it is the way I have coded in C/C++/Java for the last 20 years (well Java 16) so I am 100% certain that it works :-) (and thanks for counter vote :-)
TofuBeer
+1  A: 

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.
        }
    }

    // ...

}
BalusC