views:

556

answers:

4

What's the difference between these two methods of initializing the observers ArrayList. Or any other type for that matter. Is one faster than the other? Or am I missing some other benefit here.

class Publisher implements Observerable
{
     private ArrayList observers = new ArrayList();
}

class Publisher implements Observerable
{
    private ArrayList observers; 

    public Publisher()
    {
     observers = new ArrayList();
    }
}
+9  A: 

They're equivalent. In fact, if you compile the two you'll see that they generate exactly the same byte code:

Publisher();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   aload_0
   5:   new     #2; //class java/util/ArrayList
   8:   dup
   9:   invokespecial   #3; //Method java/util/ArrayList."<init>":()V
   12:  putfield        #4; //Field observers:Ljava/util/ArrayList;
   15:  return    
}

Given that they're the same code, there clearly can't be any speed difference :)

Note that in C# they're not quite equivalent - in C# the initializer for observers would run before the base constructor call; in Java they really are the same.

Which you use is a matter of taste. If you have several different constructors which all initialize a variable in the same way it would make sense to use the first form. On the other hand, it's generally a good idea if you have several constructors to try to make most of them call one "core" constructor which does the actual work.

Jon Skeet
Jon Skeet's edits strike again
victor hugo
Do you also get the same bytecode with an instance initializer? I would guess the answer is yes.
Michael Myers
@mmyers: Yup, exactly the same again.
Jon Skeet
If you had multiple fields, I guess you could put the instance initialisers (or code in source constructor) in a different order to the fields.
Tom Hawtin - tackline
+3  A: 

They are equal, but: the difference is that in the last example, you gain the benefit of being able to do more advanced initialization logic: error handling etc.

Silfverstrom
A: 

There's not really any difference. An advantage of the first way, is that if you have multiple constructors, you don't need to remember to initialize observers in all of them.

In the second example, you can be more flexible, if you want to adjust the value based on the constructor's arguments.

Matthew Crumley
+1  A: 

The only real difference is in the order of operations. Fields that are initialized in their declaration are evaluated before the constructor of the class is called. Fields that are initialized in a subclass in this manner will be evaluated after the super's constructor is completed but before the subclass's constructor is called.

Consider the following example:

I have a test class:

public class Tester {
 Tester (String msg) {
  System.out.println(this + ":" + msg);

 }
}

I have a super class:

public class Test  {

   protected Tester t1 = new Tester("super init block");

   Test (String constructorMsg) {
 new Tester(constructorMsg);
   }
}

and I have a subclass:

Public class TestSub extends Test {

   private Tester t2 = new Tester("sub init block");

   TestSub(String constructorMsg) {
      super(constructorMsg);
      new TTester("sub constructor");
   }

}

In my main method, I create an instance of TestSub:

public static void main(String[] args) {
 new TestSub("super constructor");

}

the results are as follows:

Tester@3e205f:super init block
Tester@bf73fa:super constructor
Tester@5740bb:sub init block
Tester@5ac072:sub constructor
akf
All of which says, for the example shown in the question, there is *no difference* - because the constructor in the second version just consists of the same call as in the field initializer in the first version. Importantly, the field initializer is called *after* the superconstructor, not before.
Jon Skeet