Use of Initializers vs Constructors in Java

2019-01-02 19:28发布

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?

9条回答
流年柔荑漫光年
2楼-- · 2019-01-02 20:22

Anonymous inner classes can't have a constructor (as they're anonymous), so they're a pretty natural fit for instance initializers.

查看更多
初与友歌
3楼-- · 2019-01-02 20:24

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.

查看更多
残风、尘缘若梦
4楼-- · 2019-01-02 20:28

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.

查看更多
登录 后发表回答