null をフラグとして使うのは、やめた方がいいと思います。
null は、ただ変数が初期化されていないことを表しているだけです。
この意味以外で、null を使わない方がいいと思います。
null をフラグとして使う
「null をフラグとして使う」というのは、「null なら xxxx」というように、null が何らかの意味を持って使われていることを指します。
例えば、下記のコードでは「null はゲストユーザを指すフラグ」として使われています。
/** * ユーザ用のヘッダを作る処理 */ public String createHeader(User user){ (…中略…) String name; if(user != null){ name = user.getName(); }else{ name = "Guest"; // null ならゲストユーザ }
問題点
これの問題点は、null が何を意味しているのか、すぐに分からないという点です。
例えば、以下のコードを見たときにnull の意味をすぐに理解できるでしょうか*1。
String header = createHeader(null);
null をフラグとして使うときの問題点はここです。
それぞれの処理において好き勝手に意味を定義して null を使用すると、コードを読むときにそれぞれの処理で null が何を意味しているかを理解する必要がでてきてしまいます。
また、上記のコードに続きがあったらどうでしょうか。
String header = createHeader(null); String body = createBody(content, null);
null が2回出てきていますが、「createHeader の引数の null 」と、「createBody の引数の null 」は意味が同じであるとは限りません。
しかし、このコードだけではそれを理解できません*2。
また、仮に理解していたとしても、読むたびに「最初の null はこういう意味で、次の null はこういう意味で…」と思い返さなければいけません。
このように、null をフラグとして使用すると、コードが途端に難しくなってしまいます。
解決策1
例えば、最初の処理であれば「ゲストユーザ」というオブジェクトを用意すれば、null をなくせます。
/** * ゲストユーザ */ private static final User GUEST = new User() { @Override public String getName() { return "Guest"; } }; /** * ゲストユーザを取得します。 * * @return ゲストユーザ */ public static User getGuest() { return GUEST; }
これを使うと、先ほどの処理は以下のようになります。
String header = createHeader(User.getGuest());
これなら、「ゲストユーザ用のヘッダーを作っている」というのが理解しやすいと思います。
また、createHeader メソッドの処理もすっきりさせることができます。
public String createHeader(User user) {
(…中略…)
String name = user.getName();
解決策2
メソッドをオーバロードして、null を局所的な範囲にとどめるという手もあります。
public String createBody(Content content){ createBody(content, null) } public String createBody(Content content1, Content content2){ (…中略…) }
これなら、先ほどのコードは以下のように書き直せます。
String header = createHeader(User.getGuest());
String body = createBody(content); // null を書かなくて済む!
まとめ
null をフラグとして使うべきではないと思います。
そのように null を使ってしまうと、コードをとても難しくしてしまうからです。
それを避ける方法は状況に応じて様々で、一概には解決できないやっかいな問題です*3。
それでも null をフラグとして使っているのを見かけたら、どうすればそれを避けることができるのか、考えてみる必要があるのではないかと思います。