- PR -

インスタンス変数の宣言について

投稿者投稿内容
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2004-03-25 00:58
私もフィールド宣言時に初期化は行わないことが多いです。
基本的にコンストラクタですべて初期化します。

ちなみに、フィールド宣言でインスタンス生成を行うのは
ちょっと怖いのでやりません。

例)private ArrayList list = new ArrayList();

何故なら、コンストラクタで例外を投げないものなら構わないのですが、
例外を投げる可能性があるときに、的確に例外処理を行えないからです。

余談ですが、ナカムラさんのサンプルでは、(staticで自分自身のインスタンス生成)
コンストラクタで例外が発生してインスタンスが生成できなかった場合に
2度とインスタンス生成ができなくなるパターンがあるので、注意が必要です。
Anthyhime
ぬし
会議室デビュー日: 2002/09/10
投稿数: 437
投稿日時: 2004-03-25 06:44
私はコンストラクタによる変数初期化は例外をキャッチしたいときとか以外は使わないです。
理由は見にくいし、初期化し忘れることがあるからです。
まぁフィールド宣言時に初期化するのもコンストラクタなんですが・・・。
シュン
ぬし
会議室デビュー日: 2004/01/06
投稿数: 328
お住まい・勤務地: 東京都
投稿日時: 2004-03-25 13:46
古い?C言語の仕様などでは、関数のローカル変数は関数の先頭で宣言する必要がありました。ですが、Javaのコンパイラはメソッド内のどの位置でも宣言することが可能です。

Javaでは、変数をメソッドの先頭で宣言してメソッドの後方で使いまわすという実装は、メリットがありません。

コード:

void AMethod(){
 A objA = new A();
 for(;:wink:{/*長い処理*/}
 for(;:wink:{/*長い処理2*/}
}

void BMethod(){
 for(;:wink:{
  B objB = new B();
  /*長い処理*/
 }
 for(;:wink:{/*長い処理2*/}
}




このように記述しておくと、objBは1番目のfor文内にスコープが限定されていることがはっきり分かります。objAが1番目のfor文内でしか実際に使用されていないとしても、そのことを判断するにはAMethod全体を読まなければなりません。後者の方がソースコードの可読性が優れているということになると思います。
また、コンパイラやJVMの実装次第ですが、スレッドが"長い処理2"を実行している時点で、objBはGC対象になるかもしれませんが、objAはGC対象にはなりません。

[追記]
>Javaでは、変数をメソッドの先頭で宣言してメソッドの後方で使いまわすという実装は、メリットがありません。

失礼しました。正しくない表現であった為に誤解されてしまったようです。「メソッド全体に対するスコープを必要としない」変数について…ということです。



[ メッセージ編集済み 編集者: シュン 編集日時 2004-03-25 15:55 ]
yuzy
大ベテラン
会議室デビュー日: 2002/02/14
投稿数: 117
投稿日時: 2004-03-25 15:07
すみません。私の勘違いから脱線させてしまいました。
深夜なので多少寝ぼけてました。

>Javaでは、変数をメソッドの先頭で宣言してメソッドの後方で使いまわすという実装は、メリットがありません。

本当にそうでしょうか?

コード:

public boolean method1() {
boolean flag = false;
if (条件1) {
if (条件1-A) {
・・・
if (条件1-A-X) {
flag = true;
}
} else if (条件1-B) {
・・・
if (条件1-B-Y) {
flag = true;
}
}
} else if (条件2) {
...
}

if (!flag) {
処理;
}
・・・
return flag;
}


みたいなに複雑なif文があった場合、みなさん全てのelseの部分にflag = false;を毎回書いてらっしゃいますか?
私は全部のelseに書くのが面倒臭いのと、どこか間違えそうで、こういう場合は先頭に flag = false; と書いてしまいます。
(もちろん、全てのローカル変更を初期化する訳ではありません。)

[ メッセージ編集済み 編集者: yuzy 編集日時 2004-03-25 15:32 ]
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2004-03-25 15:50
引用:

>Javaでは、変数をメソッドの先頭で宣言してメソッドの後方で使いまわすという実装は、メリットがありません。

本当にそうでしょうか?


えーと、元の書き込みの意図を勘違いされているような気がします。Javaでは必要なところで
変数を「宣言」するべきだと書いているだけで、初期化云々は関係ありません。

Cの話に再度脱線してしまいますが、ポインタ変数の初期化に必ず不正な値を入れておき、
デバッグしやすくするという手法がありますね。Javaではそのような考慮は必要ないの
ですが、手法としては使えるところがあるかもしれませんね。
よねKEN
ぬし
会議室デビュー日: 2003/08/23
投稿数: 472
投稿日時: 2004-03-25 15:59
横から失礼します。

引用:

yuzyさんの書き込み (2004-03-25 15:07) より:



提示のコードのパターンは私もよく使います!

引用:

シュンさんの書き込み (2004-03-25 13:46) より:
Javaでは、変数をメソッドの先頭で宣言してメソッドの後方で使いまわすという実装は、メリットがありません。



この意味は「ローカル変数の宣言場所は最小限のスコープになる場所で宣言すべし!」
という主張ではないでしょうか?

yuzyさんの提示のコード例ではflagはメソッドの各所で設定されるので、
必要最小限のスコープになるのがメソッドの一番外側ということになり、
この主張からはずれる例ではないと思います。(私の受け取った認識に間違いがなければ)

--(追加)--
何度か書き直している間にかぶった(^^;

[ メッセージ編集済み 編集者: よねKEN 編集日時 2004-03-25 16:02 ]
yuzy
大ベテラン
会議室デビュー日: 2002/02/14
投稿数: 117
投稿日時: 2004-03-25 16:14
横からたびたびお騒がせして申し訳ありません。

反論はシュンさんの記事へ、というよりもunibonさんの
「一方で、Java ではローカル変数に不定な値が入ることはない(コンパイル時にエラーになる)ので、不要な初期化に利点はないです。」
に対するものになっていました。

>Javaではそのような考慮は必要ないのですが、>手法としては使えるところがあるかもしれませんね。

ということなので、これはOKということにしておきます。
これ以上脱線する場合は別スレッドにしましょう。
(私はこれで撤退します。)

スキルアップ/キャリアアップ(JOB@IT)