- ベストアンサー
配列・クリア
かなり初歩的な質問です。 あるBeanで public static String lst_data[][] = new String[5][14]; という配列を宣言してます。 処理のなかで、 lst_data = str_data; clrPara(); としています。str_data配列をlst_dataに セットしているんですが、 clrPara()のなかで、str_dataをクリアにする 処理を行っています。 そうすると、lst_dataに一旦セットされたものが str_dataのクリアで、lst_dataもクリアされて しまっているようです。 lst_dataの値は保持するにはどのようにしたらいいので しょうか??
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
atonです。 ranxさんの#4の回答を見て自分の見落としに気がつきました。 最初の宣言は, public static String str_data[][] = new String[5][14]; だと思い込んでいたんですが, public static String lst_data[][] = new String[5][14]; だったんですね。これだと,ranxさんの言われるように上記宣言は lst_data = str_data; とした段階でちゃらになります。 が,だからといって私が#2で書いたことは意味がないわけではありません。おそらくsuigakuさんの意図は, lst_data = str_data; で一回前のデータ(lst_data → "last data" という連想)を保存し, clrPara(); 以降で str_data に新たな値を入れて処理を続けたいではないかと思っているのですが,そうだとするならば,最初の変数宣言がどうであろうと,(clone() が機能すれば) lst_data = str_data.clone(); clrPara(); で目的は達成できるはずです。 #以下余談: 単にそれだけであれば,最初の宣言は public static String lst_data[][]; でいいし,clrPara() は(内部で何をやってるのか知りませんが,もし中身をクリアするだけでよいのであれば)ranxさんの言われる通り, str_data = null; str_data = new String[5][14]; で充分でしょう。もっとも,この処理がループの中だったりするなら,何度もnewで領域確保が行われるのは気持ち悪いのはたしかですが(でも,たぶん一個一個クリアするよりは高速でしょう)。
その他の回答 (5)
- ranx
- ベストアンサー率24% (357/1463)
ご質問に対する直接の回答にはならないと思いますが、 こんな風にした方がすっきりすると思いますよ。 public class MainClass { ParameterSet lst_data; // public static にする必要性はあるのかな? ParameterSet str_data; public void main(String args[]) // とりあえず { lst_data = new ParameterSet(); ・・・・ lst_data = str_data; str_data = new ParameterSet(); ・・・・ } } public class ParameterSet { // データの実体 private String data[][]; // コンストラクタ public ParameterSet() { data = new String[5][14]; // 初期化処理 } }
補足
ありがとうございます。 ranxさんのようにかくと、 Javaぽいですね。 Javaぽいというか、オブジェクト指向言語 ということがわかります。 私はどうも今までやってたような やり方(VBとか)でやりがちです。 だから、いまいち、オブジェクト指向 を生かしたコーディングが出来てない気がします。 もっとオブジェクト指向という概念を 生かしたPGをつくりたいのですが まだまだ勉強がたりてないのだとおもいます。 なにかいい参考書やページがありましたら 教えていただきたいです。 また、よろしくお願いします。
- ranx
- ベストアンサー率24% (357/1463)
#1の回答を書いたranxです。 >> lst_dataのアドレスを参照していたから >> ですよね。クリアされちゃったのは。。 は、その通りかもしれません。が、前の回答で私が言おうとしたのは、 lst_data = str_data; とした時点で(つまりclrPara()を呼ぶ以前に) public static String lst_data[][] = new String[5][14]; と定義したものはちゃらになってしまっていますよ、ということだったのです。 このnew String[5][14]は全く無視してしまっていいということでしたら、 atonさんのおっしゃることが当たっているかもしれません。 (私としては、相変わらずsuigakuさんの意図がさっぱり分からないのですが) ただ、もしそうならば、clrPara()の中では、str_dataをクリアするのではなく、 str_data = null; とか str_data = new String[5][14]; とかやってしまった方が簡単な気がするのです けれど、それではまずいんでしょうかね。
補足
>lst_data = str_data; >とした時点で(つまりclrPara()を呼ぶ以前に) >public static String lst_data[][] = new String[5][14]; > と定義したものはちゃらになってしまっていますよ、 チャラになっちゃうってことですか。。 えーと。。でもstr_dataも [5][14]の配列なんですが。。。 もう一度定義され直されるって意味でしょうか。。 すみません。 str_data = null; とはしたくないんです。 それは、str_dataのなかにコンボのセット値も 入ってるので、nullってわけではないんですね。 初期値があるものもあるので、。。。 セットしなおしてるんです。clrParaで。
- aton
- ベストアンサー率47% (160/334)
#2の回答を書いたatonです。補足に対するアドバイスです。 >>clone() 関数を利用するには,オブジェクトが >>所属するクラスが Clonable インターフェイスを >>サポートしていることが必要 >Stringの2次元配列は、よくわかりませんでした。。 実際に lst_data = str_data; の部分を lst_data = str_data.clone(); のように変えて実行してみることを薦めます。 それでうまくいけばそれでよし,ダメならばまた補足に書いてもらえればと思います。
補足
型に互換性がありません。とでます。 String型のみ、のようです。
- aton
- ベストアンサー率47% (160/334)
Javaでは,プリミティブ(boolean, char, byte, short, int, long, float, double)以外の変数はオブジェクトとして扱われ,オブジェクトの代入は全て参照(アドレス)の代入によって行われます。String もオブジェクトですし,配列もオブジェクトです。 lst_data = str_data; では,str_dataのString配列が実際に格納されているメモリ上のアドレスがlst_dataにコピーされます。str_dataの中身がコピーされるわけではありません。 図にすると str_data --→ メモリ(xxxx番地):{{"ab","cd",..,"ef"},{"bc","de",..,"fg"},..,{"cd","ef",..,"gh"}} | |<lst_data = str_data;> ↓ str_data -+→ メモリ(xxxx番地):{{"ab","cd",..,"ef"},{"bc","de",..,"fg"},..,{"cd","ef",..,"gh"}} | lst_data -+ となり, str_data --→ メモリ(xxxx番地):{{"ab","cd",..,"ef"},{"bc","de",..,"fg"},..,{"cd","ef",..,"gh"}} | |<lst_data = str_data;> ↓ str_data --→ メモリ(xxxx番地):{{"ab","cd",..,"ef"},{"bc","de",..,"fg"},..,{"cd","ef",..,"gh"}} lst_data --→ メモリ(yyyy番地):{{"ab","cd",..,"ef"},{"bc","de",..,"fg"},..,{"cd","ef",..,"gh"}} のようには*なりません*。 このため,str_dataの中身を変更すると当然lst_dataの中身も変更されることになります。 後者のような効果を得たいのであれば,Javaでは普通 clone() 関数を使います。こんな感じです。 lst_data = str_data.clone(); ただし,clone() 関数を利用するには,オブジェクトが所属するクラスが Clonable インターフェイスをサポートしていることが必要で,またこの関数が実際にどのような振る舞いをするかは,個々のクラスでの実装に依存します。StringはClonableだったと思いますが,Stringの二次元配列がどうなのかは分かりませんので,調べてみてください。
補足
>str_dataの中身がコピーされるわけではありません。 そうですね。アドレスを参照して、中身をみてる 感じなんですよね? >clone() 関数を利用するには,オブジェクトが >所属するクラスが Clonable インターフェイスを >サポートしていることが必要 Stringの2次元配列は、よくわかりませんでした。。
- ranx
- ベストアンサー率24% (357/1463)
lst_data がクリアされているのは、str_data をクリアしたためではなく、 lst_data に str_data を代入することによって、元の lst_data を参照 するものがなくなったためではないかと思います。 どこかに保存してから代入するようにしたらどうでしょう。 saved_data = lst_data; lst_data = str_data; clrPara(); プログラムの他の部分が分からず、これが原因かどうか確信がないため、 「自信なし」です。
補足
lst_dataのアドレスを参照していたから ですよね。クリアされちゃったのは。。 でも、 saved_data = lst_data; としても、結果、アドレス参照するので 同じなのではないでしょうか??
補足
str_dataもlst_dataも[5][14]です。 >一回前のデータ(lst_data → "last data" という連想)を保存し, >clrPara(); >以降で str_data に新たな値を入れて処理を続けたい >ではないかと思っているのですが ハイ。そのとおりです。 cloneは使えなかったです。 型の互換性がないとエラーがでました。 また、clrPara()は、配列要素によっては、 クリアじゃなく、初期値をセットしているので nullや、newでセットできないのです。 何度もすみません。。