Javaに関する様々な情報をご紹介します。

Javaに関する様々な情報をご紹介します。
評価

0

Listの格納に関して

質問させていただきます。

Webでの検索機能を作っています。
問い合わせ結果を取得するメソッドで、
DBからレコードを取得してListに格納する際、

1.Listをローカル変数としてメソッドの戻り値として返す
2.Listをメンバ変数としてgetterを用意する

どちらで実装すべきか迷ってます。
1.で実装した場合は、レコード数が多い場合スタックオーバーフローが起こりえるのでしょうか?
上記を考慮して2.で実装するのが無難でしょうか?

ご回答宜しくお願いします。

6

回答

88166

閲覧

6件の回答

評価

0

ローカル変数とメンバ変数の使い分けが、
オーバーフロー対策だなんて、
寡聞にして聞いたことがないんだが。

ローカルだから領域が狭い、とか考えてるのかな。
そんなことないよ。

とりあえず、変数のスコープは狭い方がいい、
と考えておけば、大ケガはしないんじゃないかな。

評価

0

メンバ変数って、「何の」メンバ?

クラスに対してメンバ(フィールド)はどういう存在なの
か。
それによって、どちらが適切なのかが決まって来る。

ResultSetはメソッドの戻り値になってるが、実際には
Connectionのメンバだな。

アクセサクラスだとstaticやシングルトンも考えられるから、
それでメンバだと、適切な排他が必要になるが。

評価

0

@

質問者はC/C++の経験があるのかな? それでローカル変数はスタックに積まれるという意識があるのかもしれません。

Javaではローカル変数というかメソッド内で作成したオブジェクトインスタンスもスタックではなくヒープに格納されます。配列もオブジェクトでありヒープに格納されますので、C/C++のようなスタックオーバーフローの心配は基本的にありません。

※ Javaでもオブジェクト変数自体(≒ポインタ)やプリミティブ型はスタックに積まれるので、異常な再帰呼び出しなどでスタックオーバーフローがおこることはあります。

スタックの心配はせず用途に合わせて実装を決めれば良いと思います。たとえば、getterが複数回呼ばれた場合に毎回データを再作成するのなら 1. の方が適しているし、2回目以降の呼び出しでは既存データを返せば良いのであれば 2. の方が適しています。

評価

0

不良社員さん、$さん
ご回答ありがとうございます。

以下のような実装を考えてます。
2.の場合が排他が必要なのでしょうか?

1.
public class AAA {
  public List getAaaList() {
    List<Bean> list = new ArrayList<Bean>();
    Connection conn = ...
    PreparedStatement stmt = ...
    ResultSet rs = stmt.executeQuery();
    while (rs.next()) {
      list.add(bean);
    }
    return list;
  }
}

2.
public class AAA {
  List<Bean> list;

  public getAaaList() {
    return list;
  }

  public boolean searchAaa() {
    list.clear();
    Connection conn = ...
    PreparedStatement stmt = ...
    ResultSet rs = stmt.executeQuery();
    while (rs.next()) {
      list.add(bean);
    }
    return true;
  }
}

評価

0

オーバーフローと排他と、なんの関係があるんだ・・・。

競合が生じるコードなら、排他は必要だ。
そうでないなら必要ない。
投稿されたコードだけじゃ、判断できないね。

評価

0

最近ではJDBCもほぼカーソル操作なので問題ないと思うけど…

そもそもDBの取得件数は切っといたほうが良い。
※ROWNUMのBETWEENなどでリミット指定するのが一般的。

JDBCドライバ次第なのでドライバがカーソル操作ではなく全件メモリに溜め込むようなやつだとそもそもクエリ発行時点でオーバーフローで落ちるし。
また、カーソル移動時に前データを開放するかどうかもドライバ次第。

そういった面でもまずクラス変数格納かローカル変数かとか以前に件数は切るべき。


質問から6ヶ月以上経過しているので、回答を書き込むことはできません。