- PR -

オブジェクトの操作について。

1
投稿者投稿内容
docomo娘
会議室デビュー日: 2006/11/11
投稿数: 3
投稿日時: 2006-11-11 05:07
こんにちは。質問です。
オブジェクト(サンプルHogeBusinessLogicClassクラスsetBean()のInsertTableBeanClass insertBean)を参照渡し(チック)に渡し、そのオブジェクトを操作するという使い方は邪道なのでしょうか??
ループ処理でインサートを行うため、InsertTableBeanClassオブジェクトを使いまわしているのですが、あまりこうゆうソースコードを見たことがありません。

ご存知の方ご教授くださいませm_m


**** サンプル **************************************************
public WorkTableBeanClass {
private int code;
private int flg;
private String name1;
private String name2;
private BigDecimal bd1;
private BigDecimal bd2;
private BigDecimal bd3;

public int getFlg(){return this.flg;}
public void setFlg(int flg){this.code = flg;}
public int getCode(){return this.code;}
public void setCode(int code){this.code = code;}
public String getName1(){return this.name1;}
public void setName1(String name1){this.name1 = name1;}
public String getName2(){return this.name2;}
public void setName2(String name2){this.name2 = name2;}
public BigDecimal getCaluclatedNumber(){return util.caluculateNum(bd1,bd2,bd3);}
}

public InsertTableBeanClass {
private String name;
private String codeName;
private BigDecimal number;

public void setName(String name){this.name = name;}
public void setCodeName(String codeName){this.name = codeName;}
public void setNumber(BigDecimal number){this.number = number;}

}

-------------------------------------------------------------------------
public HogeBusinessLogicClass {

public void logic(){
//WorkTableBeanClassのリストを取得
SelectworkTableClass select1 = new SelectworkTableClass();
ArrayList workTableList = select1.getWorkTableList();

SelectCodeClass select2 = new SelectCodeClass();

InsertTableBeanClass insertBean = new InsertTableBeanClass();

for(i=0,i<workTableList.length();i++){

workBean = workTableList.get(i);
String codeName = select2.getCodeName(workBean.getCode());

this.setBean(workBean, item ,insertBean);

//インサート処理
db.insert(insertBean);
}

private void bean setBean(WorkTableBeanClass workBean, String codeName, InsertTableBeanClass insertBean){
if(1==workBean.getFlg()){
insertBean.setName(workBean.getName1());
}else{
insertBean.setName(workBean.getName2());
}

insertBean.setNumber(workBean.getCaluclatedNumber());
insertBean.setCodeName(codeName);
}


[ メッセージ編集済み 編集者: 初心者 編集日時 2006-11-11 05:10 ]

[ メッセージ編集済み 編集者: docomo娘 編集日時 2006-11-11 05:20 ]

[ メッセージ編集済み 編集者: docomo娘 編集日時 2006-11-11 11:26 ]
Gio
ぬし
会議室デビュー日: 2003/11/28
投稿数: 350
お住まい・勤務地: 都内から横浜の間に少量発生中
投稿日時: 2006-11-12 00:03
丸投げに近いコードは敢えて無視します。

(1) Java ではリファレンス型(インタフェースおよびクラス)の引数は「チック」などという言い方をしなくても、参照渡しと定義されています。
決して邪道ではありませんが、後述するバグにつながるおそれがあるため、プロジェクトによってはこのようなコーディングスタイルを認めないこともあるかとは思います。

(2) 問題の本質は db.insert() メソッド実行後、実際の DB への書き込みがいつ起こるか、その時引数として渡されたオブジェクトがどのような形で保持されているかによります。

DB への書き込みが即時である、もしくは、引数オブジェクトへの参照ではなくコピーが保持されているならば、引数として渡したオブジェクトをメソッド内で更新し、それを db.insert() に渡す方法で問題ないと思われます。

これらが保証されない場合は、引数オブジェクトを自前でコピーするか作り直すかしてから操作し、それを返す方(同一オブジェクトの使いまわしをしない)が安全です。
(遅延書き込みでしかも参照が保持されている場合、オブジェクトを使いまわすと最後の更新結果だけがずらっと書き込まれるバグになります。)

(3) 他のスレッドでも書いていますが、教えを乞う場合は「教授」ではなく「教示」です。
docomo娘
会議室デビュー日: 2006/11/11
投稿数: 3
投稿日時: 2006-11-12 00:26
Gioさんありがとうございますm_m 掲示板に投稿するのがはじめてでルールを無視してすいませんでした。。。

(1)→そうなのですね。参照渡しについては知りませんでした^^;掲示板をいくつか拝見したところ厳密には参照渡しではないという記事を多く読みましたので。。。

(3) →ご指摘ありがとうございます。。。

(2)→ DB への書き込みが即時かどうかはわかりませんので、下のように修正することで回避できますでしょうか?

HogeBusinessLogicClassのsetBean()をgetBean()にし、オブジェクトの使いまわしではなく、insertBeanをnew()したものを返却するよう修正。

【before】
@this.setBean(workBean, item ,insertBean);
Aprivate void bean setBean(WorkTableBeanClass workBean, String codeName, InsertTableBeanClass insertBean){}


【After】
@InsertTableBeanClass insertBean = this.getBean(workBean, item);

Aprivate InsertTableBeanClass getBean(WorkTableBeanClass workBean, String codeName){
 InsertTableBeanClass insertBean = new InsertTableBeanClass();
//処理
return insertBean;
}


[ メッセージ編集済み 編集者: docomo娘 編集日時 2006-11-12 00:28 ]

[ メッセージ編集済み 編集者: docomo娘 編集日時 2006-11-12 00:39 ]

[ メッセージ編集済み 編集者: docomo娘 編集日時 2006-11-12 00:40 ]

[ メッセージ編集済み 編集者: docomo娘 編集日時 2006-11-12 00:53 ]
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2006-11-12 00:31
>Gioさん

細かいツッコミで恐縮ですが、厳密には「参照渡し」ではないでしょう。
言語レベルでは見えない参照値を「値渡し」しているが本来の動きだと思います。
コード:
public void hoge(){
    String s1 = "aaa";
    piyo(s1);
    //s1は"aaa"のまま
}

public void piyo(String s2){
    s2 = "bbb";
}


他の言語では、本来の値渡しと参照渡しというのが区別されて存在するので、
初心者の誤解を招きやすいかなと思って、ツッコミました。

#理解されているとは思いますが、不快に思ったら申し訳ないです。
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2006-11-12 16:35
引用:

docomo娘さんの書き込み (2006-11-12 00:26) より:
Gioさんありがとうございますm_m 掲示板に投稿するのがはじめてでルールを無視してすいませんでした。。。



答える側も人間なので。しかも無報酬で善意で答えているだけなので
読むのが面倒だなってソースは敬遠してしまいますね。
回答側の心理も理解した上でうまく要点をまとめて質問すれば
回答が得やすいとは思います。

引用:

かつのりさんの書き込み (2006-11-12 00:31) より:
細かいツッコミで恐縮ですが、厳密には「参照渡し」ではないでしょう。
言語レベルでは見えない参照値を「値渡し」しているが本来の動きだと思います。



一応、Javaの場合は「参照の値渡し」です。
ですから引数で渡された参照のオブジェクトをいじればメソッド外にも波及しますが、
引数の変数に代入などを行った場合はメソッド外には波及しません。
Gio
ぬし
会議室デビュー日: 2003/11/28
投稿数: 350
お住まい・勤務地: 都内から横浜の間に少量発生中
投稿日時: 2006-11-13 11:37
>かつのりさん、nagise さん

突っ込みありがとうございます。
確かに単に参照渡しと言ってしまうと、C で言うところの void foo(A *a) と void foo(A &a) を区別しない表現になってしまいますね。(前者は Java には存在しないポインタですが)
引数オブジェクトに対する操作が有効であるであるという意味で言い切ってしまいました。
失礼しました(_ _)

> docomo娘さん

お近くの方に相談する場合は状況や環境などがおわかりでしょうから、お書きになった質問の仕方でもかまわないと思いますが、ネット上の掲示板では、そういった情報は明示しない限りまったくわかりません。
今回の内容は Java + DB のようですので、

  • OS(バージョンを含む)
  • JDK のバージョン
  • DB管理システムの名前(Oracle とか MySQL とか)とバージョン

は最低限必須かと思います。

あと、極めて個人的なことですが、私の場合は、投稿されたような機能仕様も説明されておらずコメントも重要なところには書かれていなくて自明なところに書いてあるようなソースを持ってこられたら、問答無用で突き返します(笑)

でようやく本題です。
(2) ですが、きちんとおわかりのようで安心いたしました。
この方法だと、書き込みのタイミングや書かれるまでの保持方法によらず、ソースを見ただけで少なくとも使いまわしによるバグはないことがわかります。

[ メッセージ編集済み 編集者: Gio 編集日時 2006-11-13 11:38 ]
docomo娘
会議室デビュー日: 2006/11/11
投稿数: 3
投稿日時: 2006-11-15 21:21
>Gioさん
ご指摘&ご丁寧な解説ありがとうございます。以後きをつけますm_m

>nagiseさん

ご指摘ありがとうございます。以後きをつけますm_m
1

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