Top initialization Questions

List of Tags

If 'Test' is an ordinary class, is there any difference between:

Test* test = new Test;
//and
Test* test = new Test();
Answered By: Michael Burr ( 353)

Let's get pedantic, because there are differences that can actually affect your code's behavior. Much of the following is taken from comments made to an "Old New Thing" article.

Sometimes the memory returned by the new operator will be initialized, and sometimes it won't depending on whether the type you're newing up is a POD (plain old data), or if it's a class that contains POD members and is using a compiler-generated default constructor.

  • In C++1998 there are 2 types of initialization: zero and default
  • In C++2003 a 3rd type of initialization, value initialization was added.

Assume:

struct A { int m; }; // POD
struct B { ~B(); int m; }; // non-POD, compiler generated default ctor
struct C { C() : m() {}; ~C(); int m; }; // non-POD, default-initialising m

In a C++98 compiler, the following should occur:

  • new A - indeterminate value
  • new A() - zero-initialize

  • new B - default construct (B::m is uninitialized)

  • new B() - default construct (B::m is uninitialized)

  • new C - default construct (C::m is zero-initialized)

  • new C() - default construct (C::m is zero-initialized)

In a C++03 conformant compiler, things should work like so:

  • new A - indeterminate value
  • new A() - value-initialize A, which is zero-initialization since it's a POD.

  • new B - default-initializes (leaves B::m uninitialized)

  • new B() - value-initializes B which zero-initializes all fields since its default ctor is compiler generated as opposed to user-defined.

  • new C - default-initializes C, which calls the default ctor.

  • new C() - value-initializes C, which calls the default ctor.

So in all versions of C++ there's a difference between "new A" and "new A()" because A is a POD.

And there's a difference in behavior between C++98 and C++03 for the case "new B()".

This is one of the dusty corners of C++ that can drive you crazy. When constructing an object, sometimes you want/need the parens, sometimes you absolutely cannot have them, and sometimes it doesn't matter.

How would you initialise a static Map in Java?

Method one: Static initializer
Method two: instance initialiser (anonymous subclass) or some other method?

What are the pros and cons of each?

Here is an example illustrating two methods:

import java.util.HashMap;
import java.util.Map;

public class Test {
    private static final Map<Integer, String> myMap = new HashMap<Integer, String>();
    static {
        myMap.put(1, "one");
        myMap.put(2, "two");
    }

    private static final Map<Integer, String> myMap2 = new HashMap<Integer, String>(){
        {
            put(1, "one");
            put(2, "two");
        }
    };
}
Answered By: Miserable Variable ( 224)

The instance initialiser is just syntactic sugar in this case, right? I don't see why you need an extra anonymous class just to initialize. And it won't work if the class being created is final.

You can create an immutable map using a static initialiser too:

public class Test {
    private static final Map<Integer, String> myMap;
    static {
        Map<Integer, String> aMap = ....;
        aMap.put(1, "one");
        aMap.put(2, "two");
        myMap = Collections.unmodifiableMap(aMap);
    }
}
210
Macarse

I am willing to create a list of options to test something.

I was doing:

ArrayList<String> places = new ArrayList<String>();
places.add("Buenos Aires");
places.add("Córdoba");
places.add("La Plata");

I refactor the code doing:

ArrayList<String> places = new ArrayList<String>(
    Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));

Is there a better way of doing this?

Thanks for reading!

Answered By: coobird ( 170)

Actually, probably the "best" way to initialize the ArrayList is the method you wrote, as it does not need to create a new List in any way:

ArrayList<String> list = new ArrayList<String>();
    list.add("A");
    list.add("B");
    list.add("C");

The catch is that there is quite a bit of typing required to refer to that list instance.

There are alternatives, such as making an anonymous inner class with an instance initializer (also known as an "double brace initialization"):

ArrayList<String> list = new ArrayList<String>() {{
    add("A");
    add("B");
    add("C");
}}

However, I'm not too fond of that method because what you end up with is a subclass of ArrayList which has an instance initializer, and that class is created just to create one object -- that just seems like a little bit overkill to me.

What would be nice is if the Collection Literals proposal for Project Coin is accepted, so we can have list literals in Java 7:

List<String> list = ["A", "B", "C"];

Unfortunately it won't help you here, as it will initialize a List rather than an ArrayList, and furthermore, it's not available yet, if it ever will be.

I have a large array in C (not C++ if that makes a difference). I want to initialize all members to the same value. I could swear I once knew a simple way to do this. I could use memset() in my case, but isn't there a way to do this that is built right into the C syntax?

Answered By: aib ( 260)

Unless that value is 0 (in which case you can omit some part of the initializer and the corresponding elements will be initialized to 0), there's no easy way.

Don't overlook the obvious solution, though:

int myArray[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };

Elements with missing values will be initialized to 0:

int myArray[10] = { 1, 2 }; //initialize to 1,2,0,0,0...

So this will initialize all elements to 0:

int myArray[10] = { 0 }; //all elements 0

In C++, an empty initialization list will also initialize every element to 0:

int myArray[10] = {}; //all elements 0 in C++

Remember that objects with static storage duration will initialize to 0 if no initializer is specified:

static int myArray[10]; //all elements 0

And that "0" doesn't necessarily mean "all-bits-zero", so using the above is better and more portable than memset(). (Floating point values will be initialized to +0, pointers to null value, etc.)

183
Jim Ferrans

In Hidden Features of Java the top answer mentions Double Brace Initialization, with a very enticing syntax:

Set<String> flavors = new HashSet<String>() {{
    add("vanilla");
    add("strawberry");
    add("chocolate");
    add("butter pecan");
}};

This idiom creates an anonymous inner class with just an instance initializer in it, which "can use any [...] methods in the containing scope".

Main question: Is this as inefficient as it sounds? Should its use be limited to one-off initializations? (And of course showing off!)

Second question: The new HashSet must be the "this" used in the instance initializer ... can anyone shed light on the mechanism?

Third question: Is this idiom too obscure to use in production code?

Summary: Very, very nice answers, thanks everyone. On question (3), people felt the syntax should be clear (though I'd recommend an occasional comment, especially if your code will pass on to developers who may not be familiar with it).

On question (1), The generated code should run quickly. The extra .class files do cause jar file clutter, and slow program startup slightly (thanks to @coobird for measuring that). @Thilo pointed out that garbage collection can be affected, and the memory cost for the extra loaded classes may be a factor in some cases.

Question (2) turned out to be most interesting to me. If I understand the answers, what's happening in DBI is that the anonymous inner class extends the class of the object being constructed by the new operator, and hence has a "this" value referencing the instance being constructed. Very neat.

Overall, DBI strikes me as something of an intellectual curiousity. Coobird and others point out you can achieve the same effect with Arrays.asList, varargs methods, Google Collections, and the proposed Java 7 Collection literals. Newer JVM languages like Scala, JRuby, and Groovy also offer concise notations for list construction, and interoperate well with Java. Given that DBI clutters up the classpath, slows down class loading a bit, and makes the code a tad more obscure, I'd probably shy away from it. However, I plan to spring this on a friend who's just gotten his SCJP and loves good natured jousts about Java semantics! ;-) Thanks everyone!

Answered By: coobird ( 146)

Update: Added an experiment to evaluate the performance of double brace initialization.

Here's the problem when I get too carried away with anonymous inner classes:

2009/05/27  16:35             1,602 DemoApp2$1.class
2009/05/27  16:35             1,976 DemoApp2$10.class
2009/05/27  16:35             1,919 DemoApp2$11.class
2009/05/27  16:35             2,404 DemoApp2$12.class
2009/05/27  16:35             1,197 DemoApp2$13.class

/* snip */

2009/05/27  16:35             1,953 DemoApp2$30.class
2009/05/27  16:35             1,910 DemoApp2$31.class
2009/05/27  16:35             2,007 DemoApp2$32.class
2009/05/27  16:35               926 DemoApp2$33$1$1.class
2009/05/27  16:35             4,104 DemoApp2$33$1.class
2009/05/27  16:35             2,849 DemoApp2$33.class
2009/05/27  16:35               926 DemoApp2$34$1$1.class
2009/05/27  16:35             4,234 DemoApp2$34$1.class
2009/05/27  16:35             2,849 DemoApp2$34.class

/* snip */

2009/05/27  16:35               614 DemoApp2$40.class
2009/05/27  16:35             2,344 DemoApp2$5.class
2009/05/27  16:35             1,551 DemoApp2$6.class
2009/05/27  16:35             1,604 DemoApp2$7.class
2009/05/27  16:35             1,809 DemoApp2$8.class
2009/05/27  16:35             2,022 DemoApp2$9.class

These are all classes which were generated when I was making a simple application, and used copious amounts of anonymous inner classes -- each class will be compiled into a separate class file.

The "double brace initialization", as already mentioned, is an anonymous inner class with a instance initialization block, which means that a new class is created for each "initialization", all for the purpose of usually making a single object.

Considering that the Java Virtual Machine will need to read all those classes when using them, that can lead to some time in the bytecode verfication process and such. Not to mention the increase in the needed disk space in order to store all those class files.

It seems as if there is a bit of overhead when utilizing double-brace initialization, so it's probably not such a good idea to go too overboard with it. But as Eddie has noted in the comments, it's not possible to be absolutely sure of the impact.


Just for reference, double brace initialization is the following:

List<String> list = new ArrayList<String>() {{
    add("Hello");
    add("World!");
}};

It looks like a "hidden" feature of Java, but it is just a rewrite of:

List<String> list = new ArrayList<String>() {

    // Instance initialization block
    {
        add("Hello");
        add("World!");
    }
};

So it's basically a instance initialization block that is part of an anonymous inner class.


As an added note, if Joshua Bloch's Collection Literals proposal for Project Coin goes through, we may be able to see these kinds of syntax in Java 7:

List<Integer> intList = [1, 2, 3, 4];

Set<String> strSet = {"Apple", "Banana", "Cactus"};

Map<String, Integer> truthMap = { "answer" : 42 };

If this change makes it to Java 7, it may eliminate a good portion of the use cases for double brace initialization.


Experiment

Here's the simple experiment I've tested -- make 1000 ArrayLists with the elements "Hello" and "World!" added to them via the add method, using the two methods:

Method 1: Double Brace Initialization

List<String> l = new ArrayList<String>() {{
  add("Hello");
  add("World!");
}};

Method 2: Instantiate an ArrayList and add

List<String> l = new ArrayList<String>();
l.add("Hello");
l.add("World!");

I created a simple program to write out a Java source file to perform 1000 initializations using the two methods:

Test 1:

class Test1 {
  public static void main(String[] s) {
    long st = System.currentTimeMillis();

    List<String> l0 = new ArrayList<String>() {{
      add("Hello");
      add("World!");
    }};

    List<String> l1 = new ArrayList<String>() {{
      add("Hello");
      add("World!");
    }};

    /* snip */

    List<String> l999 = new ArrayList<String>() {{
      add("Hello");
      add("World!");
    }};

    System.out.println(System.currentTimeMillis() - st);
  }
}

Test 2:

class Test2 {
  public static void main(String[] s) {
    long st = System.currentTimeMillis();

    List<String> l0 = new ArrayList<String>();
    l0.add("Hello");
    l0.add("World!");

    List<String> l1 = new ArrayList<String>();
    l1.add("Hello");
    l1.add("World!");

    /* snip */

    List<String> l999 = new ArrayList<String>();
    l999.add("Hello");
    l999.add("World!");

    System.out.println(System.currentTimeMillis() - st);
  }
}

Please note, that the elapsed time to initialize the 1000 ArrayLists and the 1000 anonymous inner classes extending ArrayList is checked using the System.currentTimeMillis, so the timer does not have a very high resolution. On my Windows system, the resolution is around 15-16 milliseconds.

The results for 10 runs of the two tests were the following:

Test1 Times (ms)           Test2 Times (ms)
----------------           ----------------
           187                          0
           203                          0
           203                          0
           188                          0
           188                          0
           187                          0
           203                          0
           188                          0
           188                          0
           203                          0

As can be seen, the double brace initialization has a noticeable execution time of around 190 ms.

Meanwhile, the ArrayList initialization execution time came out to be 0 ms. Of course, the timer resolution should be taken into account, but it is likely to be under 15 ms seconds.

So, there seems to be a noticeable difference in the execution time of the two methods. It does appear that there is indeed some overhead in the two initialization methods.

And yes, there were 1000 .class files generated by compiling the Test1 double brace initialization test program.

Finally, thank you for reading this extremely long answer!