Javaについてです。

以下のソース1、2とでは、メモリの消費に差が出ますか?
「MAX==20000」程の処理を行う予定があります。

ソース1
for (int i = 0; i < MAX; i++) {
 Hoge hoge = new Hoge();//ループ内で毎回変数を宣言
 (処理)
}

ソース2
Hoge hoge = null;//ループ外で変数を一度だけ宣言
for (int i = 0; i < MAX; i++) {
 hoge = new Hoge();
 (処理)
}

また、ループ内の最後の行で、hoge = null;を書くのと書かないとではどうでしょうか。
フィールドと違い、ローカル変数にnullを入れるのはメモリ消費的には無意味と聞いたことがあるのですが本当でしょうか。

回答の条件
  • 1人3回まで
  • 登録:2008/09/21 23:28:29
  • 終了:2008/09/28 23:13:23

ベストアンサー

id:bulldra No.4

池田仮名回答回数6ベストアンサー獲得回数12008/09/25 07:03:57

ポイント40pt

コメントへのご回答ですが、URLの例はインスタンスの内部変数を使う前に初期化することで生成しないという話であり、

特定条件において「生成コスト*使用回数 + 解放コスト > 初期化コスト」で有る場合に有用な方法です。

これはご質問内ののHoge()の変数がたとえばint x, int yだけだった場合に使い回しをして、

生成処理をしないで初期化というような意味になります。


Hoge hoge = new Hoge();

for (int i = 0; i < MAX; i++) {

/* hogeのインスタンス変数を初期化 */

 hoge.init(xx, yy);

 (処理)

}


ただし、hogeを他から参照変数として使用している場合などは当然、参照先が変更されますし、

初期化処理の仕様誤解やクラス定義を変更したときの初期化処理の変更忘れといったバグの温床になるので注意が必要です。

以上はhogeの内部変数を変更する場合の副作用であるのでHogeの中身が一切変わらないのであれば

forの外どころかプログラム全体で1回だけ生成して一切作り直さない方がよいでしょう。

その場合はデザインパターンでいうところのシングルトンパターンなどが参考になります。

余談ですが現在のJDKであると文字列型の直接演算は最適化処理でStringBuillderという文字列生成クラスを使う

処理に変換されるため、StringBufferを使うやり方はむしろ遅くなる場合が多いと言われています。

以上分かりづらかったかもしれませんがご参考までに

その他の回答(4件)

id:newta No.1

newta回答回数68ベストアンサー獲得回数72008/09/22 01:37:30

ポイント20pt

あまり変わらないと思います。

ソース2のとき

hoge = new Hoge();

とした瞬間、以前参照していたインスタンス参照がはずれGC対象になると思うので、

nullを明示的にセットしてもしなくても変わらないと思います。

フィールドでもGC対象になるかならないかが重要であって、

明示的にnullセットするとかはあんまり関係ないと思います。

id:ahirusan No.2

あひる回答回数229ベストアンサー獲得回数32008/09/22 08:02:09

ポイント20pt

メモリ効率に関してはどちらもまったく一緒ですね。どちらの場合もすぐにガベージコレクションの対象となります。

また、最後にNULLを入れてやる件ですが、ガベージコレクションの対象になるのが僅かに早くなるだけで、実質的には何の意味もないと思います。明らかに不要な参照が残ってしまうような場合でないかぎり、無用なコードです。

id:bulldra No.3

池田仮名回答回数6ベストアンサー獲得回数12008/09/22 23:24:40

ポイント20pt

オブジェクトがガーベージコレクション対象になるのは参照が外れた時であるのでnullの代入とともに「変数がスコープ外にあること」を意識されると良いと思います。

質問内容について強いて言えばソース2の方が最後の一回についての参照がもう一段階上の括弧閉じの部分まで残り続ける分は損だと考えられます。

とはいえ参照外になったところで即座に解放処理が行われるわけではないため注意が必要です。

JavaVMのメモリ構造とガーベージコレクションについては以下のURLが参考になると思われます。

http://www.atmarkit.co.jp/fjava/rensai3/devedge03/devedge03_1.ht...

id:kurokumi

ありがとうございます。

皆さんのご意見をまとめると、ほとんど変わらないということのようなんですが。

下記のような解説を見つけたのですが、どうなんでしょうか。

http://www.sgnet.co.jp/java/chapter0502.html

2008/09/24 23:42:55
id:bulldra No.4

池田仮名回答回数6ベストアンサー獲得回数12008/09/25 07:03:57ここでベストアンサー

ポイント40pt

コメントへのご回答ですが、URLの例はインスタンスの内部変数を使う前に初期化することで生成しないという話であり、

特定条件において「生成コスト*使用回数 + 解放コスト > 初期化コスト」で有る場合に有用な方法です。

これはご質問内ののHoge()の変数がたとえばint x, int yだけだった場合に使い回しをして、

生成処理をしないで初期化というような意味になります。


Hoge hoge = new Hoge();

for (int i = 0; i < MAX; i++) {

/* hogeのインスタンス変数を初期化 */

 hoge.init(xx, yy);

 (処理)

}


ただし、hogeを他から参照変数として使用している場合などは当然、参照先が変更されますし、

初期化処理の仕様誤解やクラス定義を変更したときの初期化処理の変更忘れといったバグの温床になるので注意が必要です。

以上はhogeの内部変数を変更する場合の副作用であるのでHogeの中身が一切変わらないのであれば

forの外どころかプログラム全体で1回だけ生成して一切作り直さない方がよいでしょう。

その場合はデザインパターンでいうところのシングルトンパターンなどが参考になります。

余談ですが現在のJDKであると文字列型の直接演算は最適化処理でStringBuillderという文字列生成クラスを使う

処理に変換されるため、StringBufferを使うやり方はむしろ遅くなる場合が多いと言われています。

以上分かりづらかったかもしれませんがご参考までに

id:nake No.5

nake回答回数87ベストアンサー獲得回数02008/09/26 18:09:21

ポイント20pt

ソース2のほうがメモリー消費に関してはよさそうに思われます。

http://www.sgnet.co.jp/java/chapter0502.html

Stringオブジェクトは特別なので、普通のオブジェクトと比較してもあまり意味がないかと。

id:kurokumi

例に挙げたURLはStringオブジェクトではなく、StringBufferですよね。

2008/09/27 01:28:43

コメントはまだありません

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

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

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

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません