JAVAプログラミングについて質問です。

NULLと""(ダブルクォーテーション2つ)の違いについてのふとした疑問です。
String型の変数をクリアするときは(1)と(2)のどちらがよいでしょうか
(1)変数名 = null;
(2)変数名 = "";
他人のコードを読むと(1)が多く、(2)は初心者の方に多いように思えます。
どちらでも意味的にはよいのですが、それぞれ選んだ理由をおしえてください。
プログラミングの作法的な観点からの回答などであればうれしいですが、どんなことでもいいです。

回答の条件
  • 1人2回まで
  • 登録:
  • 終了:2007/01/31 09:53:49
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

回答11件)

id:tokuya_n No.1

回答回数56ベストアンサー獲得回数7

ポイント16pt

ユーザは「""」を入力するかも知れません。

ユーザが「null」を入力することはないでしょう。

従って、初期化というなら「null」のほうが良いと思います。


パフォーマンスとかメモリをケチるとかその辺の理由もあるでしょう。

空文字かどうかのチェックしたければ、大抵は両方を見ることになるわけですか。

id:cg_121

なるほど。

初期化されてるのか入力値なのかの区別ということですね。ありがとうございます。

2007/01/26 13:55:45
id:hissssa No.2

回答回数428ベストアンサー獲得回数129

ポイント16pt

String型変数にnullを指定するということは、その変数を明示的に「値が設定されていない」状態にすることになります。一方、""を指定するのは「空白な文字列を割り当てる」事を意味します。

この、「値が割り当てられているか否か」ということが、使い方に関わってきます。分かりやすい例では、nullを割り当てた変数に対して参照を行うと、Null Pointer Exceptionが発生することになります。

  String st1r = null;

  String str2 = "Value:"+str1;  ←Exceptionになる

では空白文字列を設定した方がいいかとなると、そういうわけでもありません。変数に値が割り当てられているか否かで処理を分岐するような場合です。

  String str = null;

  <<何かの処理>>

  if( str!=null ) {

    <<何かの処理で値が割り当てられた場合>>

  } else {

    <<そうでない場合>>

  }

処理によっては、空白文字列も意味を持つこともありますので、上記のような判定で空白文字列か否かを基準に使うのは正しくないとなります。

まぁ要はケースバイケースということですね。

id:cg_121

。。。すみません

public static void main(String args[]){

String str1 = null;

String str2 = "Value:"+str1;

}

↑Exceptionは起きませんでした。。。でも意味はわかりますよ。

こちらも、

>処理によっては、空白文字列も意味を持つことも

とうことで、条件分岐の判定で混同してしまう問題があるということですね?ありがとうございます。

2007/01/26 15:13:25
id:Kumappus No.3

回答回数3784ベストアンサー獲得回数185

ポイント16pt

hissssaさんとほぼ同じ意見です。

Null Pointer Exception例外をcatchして動くようなプログラミングをしたいのならnullを使うのもありかと思います。

try{

何かの処理

}catch( NullPointerException e){

初めて値が入るとみなして設定させる処理

}

など。

例外ハンドラーを使う書き方はうまく使うとif文のネストや条件の列挙を減らして全体の見通しをよくすることができます。

しかし空文字列の判定にnullを使うというのはプログラムの意味的にはおかしいですね。たぶんあとで混乱する元になりそうな気がします。

id:cg_121

つまり、(1)のようにNullで初期化するとNullPointerExceptionを利用した書き方もできる、ということですね。ありがとうございます。

では、変数が空であるという判定にnullを使うと、なぜおかしいのでしょうか?

2007/01/26 15:57:43
id:dev_zer0 No.4

回答回数332ベストアンサー獲得回数25

ポイント16pt

Stringをクラスとして認識しているか、プリミティブ型と認識しているかの違いと思われます。

JavaではStringクラスは他のクラスとは違い、文字列の連結を+で行うことができますし、

JavaのルートクラスであるObjectクラスにはtoStringメソッドが存在します。


私の場合、使い捨てのいわゆる「動けばいいや」的なプログラムを作る場合は""でクリアしてしまい、

できるだけ忌々しいNullPointerExceptionを出さないようにします。

そして、仕事で作る場合は、バグの兆候を示すNullPointerExceptionを

可能な限り検出する確率を上げたいのでnullでクリアします。

id:cg_121

きちんとしたものを作るときは、Nullのクリアの方がいいということですかね。参考にさせていただきます。ありがとうございます。

2007/01/26 20:29:48
id:b-wind No.5

回答回数3344ベストアンサー獲得回数440

ポイント16pt

自分なら、

・初期化をしたいなら null

・初期値を設定したいなら "" (空文字列)

を使うと思います。

null は明示的に値が存在しない事を表すので本来的には意味が近いはず。


Nullで初期化するとNullPointerExceptionを利用した書き方もできる

可能では有りますが、大抵の場合推奨されません。

理由はいくつか有りますが、

・NullPointerException が RuntimeException であるために文法上 catch を強制されず、取りこぼす可能性がある。

・NullPointerException に限らず、Exception の発生は現在の Java の実装においてコストが高い。(負荷が高い)

ため、正常系の実装としては避けるべきだと思います。

もちろん、本来の意味の Exception の発生は問題ありません。(アルゴリズムのミスなどで null でないはずの場所で null だったなど)


では、変数が空であるという判定にnullを使うと、なぜおかしいのでしょうか?

変数が「空」である判定なら問題ありません。

id:Kumappus さんは「空文字列」の比較に使うのはおかしいと仰っています。

良いか悪いかは置くとして、変数が「空(null)」と「空文字列」とはプログラム上別の意味を持っているということです。

id:cg_121

う~ん、だんだん難しくなってきました。つまり逆にいうと、

・初期化には""は使わない。

・初期値を設定するときにはNullは使わない。

ということですか?

今度は「初期化」と「初期値を設定する」ことの違いがわからなくなってしまいました・・・。

たとえば宣言が、

String 変数名 = new String();

のような変数の場合は、初期値が無いのでどちらかというと「クリア」=「初期化」だと思うので、Nullのほうですかね。。。?

>・NullPointerException が RuntimeException であるために文法上 catch を強制されず、取りこぼす可能性がある。

catchしなくてもコンパイルできるという意味ですよね?この場合、NullPointerExceptionを想定しているはずですが、ついうっかり、ということがあると面倒ですよね。なるほど。

>・NullPointerException に限らず、Exception の発生は現在の Java の実装においてコストが高い。(負荷が高い)

あまり使わないほうがいいかもしれませんね。。

id:Kumappus さんは「空文字列」の比較に使うのはおかしいと仰っています。

確かに、「空文字列の判定に・・・」と仰ってますね。意味を間違えたようです。

2007/01/26 21:13:17
id:iwaim No.6

回答回数215ベストアンサー獲得回数19

ポイント16pt

では、変数が空であるという判定にnullを使うと、なぜおかしいのでしょうか?

「空文字列」と「null」が別物だから。

id:cg_121

どう別物であるのか、普段どう意識されているのか教えていただけるとありがたいです。

2007/01/26 21:25:50
id:flashrod No.7

回答回数31ベストアンサー獲得回数3

ポイント16pt

変数が初期化されている/されていないということと、変数の値が何も指してないことを表している(null)/長さ0の文字列を表している("")は、まったく異なるものです。どう別物なのか?と聞かれても困るのですが、別物として扱うことができるようにjavaはそういう仕様になっているわけです。

java ではローカル変数で String s; と書いたとき、sは初期化されていません。初期化されてない変数の値を参照するとコンパイルエラーになります。クラス変数、インスタンス変数はnullで初期化される仕様です。

String s = null;と書けばsはnullで初期化されます。

String s = "";と書けばsは""で初期化されます。

sがnullかどうか調べたいときは if (s==null)と書きますし、

sが""かどうか調べたいときは if (s.equals(""))と書きます。

そして("" == null)や("".equals(null))は必ずfalseになります。

「クリアする」というのはあなたが作成するプログラムの仕様としてあなたが決めることです。nullを代入するのをクリアすると決めてもよいし、""を代入するのをクリアすると決めても良いのです。

それはあなたが解決したい問題の種類によります。常に何かを指した状態を維持したいのであれば""を使えばよいし、そうでないならnullを使うほうが簡単です。

null(何も指してない)と空(長さ0の文字列)の違いを意識したいのであれば、C言語か、アセンブリ言語レベルの低レベルなプログラミングを学習すればよいと思います。

id:cg_121

ありがとうございます。

(1)、(2)のどちらを選ぶかはそのプログラムの仕様で決まり、それは作る人が決めればいいということですね。

では実際、皆さんはどちらの仕様で作っているのでしょう?またどういった理由で決めているのでしょう?それほどレアなケースではないと思うのですが、どうでしょう。

2007/01/26 22:46:51
id:endeavor No.8

回答回数78ベストアンサー獲得回数1

ポイント16pt

ケースバイケースだと思いますよ。

初期化すら失敗している、あるいは不正に値がNullになっていることエラーとして検地したいのであればNullPointerExceptionを発生させるためにNullを使いますし、画面表示に初期値をそのまま使うのでNullであれば(Exceptionが発生して)困る場合は""を使います。

id:cg_121

ありがとうございます。

2007/01/27 12:42:02
id:matsOS No.9

回答回数34ベストアンサー獲得回数2

ポイント8pt

とりあえずnull派です。


何も無い順に書くとこんな感じですが・・・

  1. null は空白文字列すら存在しない状態。
  2. "" は空白文字列という長さゼロの文字列が存在している状態。

"" だとクリアせずに変数に文字列を代入した気分になります。

String含めてどんな変数にしろ、色々変化する値はプログラム中で与えたいので、null でクリアしたくなります。

id:cg_121

変数名 = ""は、クリアでなく文字列の代入という気分。となると、

何らかの値が入った変数に""を代入する→""が入ったので前の値は消された→クリアした

という考えは、あまりしないということでしょうか?

ありがとうございます。

2007/01/28 12:33:07
id:matsOS No.10

回答回数34ベストアンサー獲得回数2

ポイント8pt

追記。


オブジェクトを設計した際に、クリアした際にとる値(初期値とか)は定義するものなんで、その値に従えばいいです。

それが、空白文字列なら””でいいし、”名前を入力してください”というコメントかもしれない。


でも、特に戻すべき値が明示されず、プログラムの都合上クリアしたいだけならば、nullの方が気分的に良いというわけです。

id:cg_121

クリアした際にとる値を定義したことは、数えるほどしかないです。。。

あまりしないものかと思ってました。

参考にいたします。ありがとうございます。

2007/01/30 14:41:50
id:Strada No.11

回答回数18ベストアンサー獲得回数1

ポイント16pt

nullか""(空文字)かという議論は他の人にお任せしまして、私なりの意見を言えば、「String型の変数を初期化」する必要はほとんどありません。

初期化という意味が、(ローカル)変数などを使用した後にメモリを開放するようなイメージで使われているならば不要といえます。

>|java|

public void doSomething()

{

String str = "abc";

// 処理

str = null; // or "";

}

||<

このような意味でstrに再度nullを代入したところで、無駄な処理が増えるだけです。

どちらにせよこの変数strはローカルでしか使用されないため、メソッドを抜けてしまえば"abc"というインスタンスはGCの対象となります。

(厳密には文字列は特別なプールにキャッシュされるのでGCの対象となるかはJVMの実装によるかもしれない)

よってメモリの節約にはなりません。

また、

>|java|

public void doSomething()

{

String str = null;

// (中略)

str = "abc";

// 処理

str = "efg";

}

||<

というように最初に変数を宣言し、そのときに初期化するのは空文字かnullかという話であるならば、原則として変数の宣言は使用するときにその都度行う方が好ましい為に次のようなコードとなります。

>|java|

public void doSomething()

{

// (中略)

String abc = "abc";

// 処理

String efg = "efg";

}

||<

これに関してはコーディング規約に関連する話題となります。

ただし、try-catch節の外でどうしても変数の宣言が必要という場合はnullで初期化しておく事が好ましくなります。(JDBCでConnectionの処理を行う場合が代表的ですね)

理由としては、""(空文字)は意味のある文字列であり、このケースでは「(初期化が必要なケースで)まだ初期化していない」からです。

また、Beanなどのインスタンス変数の初期値としてのStringに関しては、好みとしか言いようがありません。

>|java|

public class Book

{

private String title = null;

}

||<

ただし、省略した場合にnullがデフォルト値としてインスタンス変数に設定されることや、空文字に意味がある場合もあることを考慮するとnullのが好ましいのでは?と私は考えます。

以上、他の方とは異なる見方ですが、参考になれば幸いです。

id:cg_121

参考になります。ありがとうございます。

2007/01/30 14:48:35
  • id:cg_121
    回答番号でいうと

    ヌル派  :1,4,9,11
    場合による:2,3,7,8
    その他  :5,6

    ですかね。回答ありがとうございました。
    場合による人が結構いますね。私も場合によるかな?と思ったけれど、みんなどうしてるんだろう?というのと、ハッキリした回答があればいいのに、と思って質問した次第です。
  • id:Kumappus
    プログラム上の意味論でとるか実装上の要件でとるか、なんで人によって、状況によって変わるでしょうね。
    オブジェクト全体をなくしたいのか、オブジェクトの中のアトリビュートを初期値に設定したいのか とも言えるけど。

    私の解答は意味論的な話です。

    ただ、id:iwaimさんの回答に対するid:cg_121さんのコメントから判断すると、あまりプラグマティックに考えずに一度オブジェクト指向の基本的なところを学習されてから、もう一度自分でどっちがいいか考えてみた方がいいのではないかと思います。

    (う、なんとなくTB先の人も何か混乱してるのではという気がしてきた…)

この質問への反応(ブックマークコメント)

トラックバック

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません