• ベストアンサー

配列・クリア

かなり初歩的な質問です。 ある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の値は保持するにはどのようにしたらいいので しょうか??

  • Java
  • 回答数6
  • ありがとう数5

質問者が選んだベストアンサー

  • ベストアンサー
  • aton
  • ベストアンサー率47% (160/334)
回答No.5

 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で領域確保が行われるのは気持ち悪いのはたしかですが(でも,たぶん一個一個クリアするよりは高速でしょう)。

suigaku
質問者

補足

str_dataもlst_dataも[5][14]です。 >一回前のデータ(lst_data → "last data" という連想)を保存し, >clrPara(); >以降で str_data に新たな値を入れて処理を続けたい >ではないかと思っているのですが ハイ。そのとおりです。 cloneは使えなかったです。 型の互換性がないとエラーがでました。 また、clrPara()は、配列要素によっては、 クリアじゃなく、初期値をセットしているので nullや、newでセットできないのです。 何度もすみません。。

その他の回答 (5)

  • ranx
  • ベストアンサー率24% (357/1463)
回答No.6

ご質問に対する直接の回答にはならないと思いますが、 こんな風にした方がすっきりすると思いますよ。  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];   // 初期化処理   }  }

suigaku
質問者

補足

ありがとうございます。 ranxさんのようにかくと、 Javaぽいですね。 Javaぽいというか、オブジェクト指向言語 ということがわかります。 私はどうも今までやってたような やり方(VBとか)でやりがちです。 だから、いまいち、オブジェクト指向 を生かしたコーディングが出来てない気がします。 もっとオブジェクト指向という概念を 生かしたPGをつくりたいのですが まだまだ勉強がたりてないのだとおもいます。 なにかいい参考書やページがありましたら 教えていただきたいです。 また、よろしくお願いします。

  • ranx
  • ベストアンサー率24% (357/1463)
回答No.4

#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]; とかやってしまった方が簡単な気がするのです けれど、それではまずいんでしょうかね。

suigaku
質問者

補足

>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)
回答No.3

 #2の回答を書いたatonです。補足に対するアドバイスです。 >>clone() 関数を利用するには,オブジェクトが >>所属するクラスが Clonable インターフェイスを >>サポートしていることが必要 >Stringの2次元配列は、よくわかりませんでした。。  実際に lst_data = str_data; の部分を lst_data = str_data.clone(); のように変えて実行してみることを薦めます。  それでうまくいけばそれでよし,ダメならばまた補足に書いてもらえればと思います。

suigaku
質問者

補足

型に互換性がありません。とでます。 String型のみ、のようです。

  • aton
  • ベストアンサー率47% (160/334)
回答No.2

 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の二次元配列がどうなのかは分かりませんので,調べてみてください。

suigaku
質問者

補足

>str_dataの中身がコピーされるわけではありません。   そうですね。アドレスを参照して、中身をみてる 感じなんですよね? >clone() 関数を利用するには,オブジェクトが >所属するクラスが Clonable インターフェイスを >サポートしていることが必要 Stringの2次元配列は、よくわかりませんでした。。

  • ranx
  • ベストアンサー率24% (357/1463)
回答No.1

lst_data がクリアされているのは、str_data をクリアしたためではなく、 lst_data に str_data を代入することによって、元の lst_data を参照 するものがなくなったためではないかと思います。 どこかに保存してから代入するようにしたらどうでしょう。 saved_data = lst_data; lst_data = str_data; clrPara(); プログラムの他の部分が分からず、これが原因かどうか確信がないため、 「自信なし」です。

suigaku
質問者

補足

lst_dataのアドレスを参照していたから ですよね。クリアされちゃったのは。。 でも、 saved_data = lst_data; としても、結果、アドレス参照するので 同じなのではないでしょうか??

関連するQ&A

  • 配列表記について

    質問させてください。 以前から気になっていたのですが、 配列を宣言するときに int型の場合  int num[] = new int[5]; と宣言するのにたいして String型(インスタンス)の場合  String[] str = new String[5]; と一般的に書くのはどうしてなのでしょうか? ちなみにどちらでもコンパイルとおりますよね。

    • ベストアンサー
    • Java
  • Javaで配列を定義する方法

    こんにちは、片岡といいます。 Java言語で配列を定義する場合、以下の二つの書式に違いはありますか。 違いがあるとすれば、どのような違いですか。 また、違いがないのならば、どちらの記述がよいのですか。 ご存知の方はいらっしゃいませんか。 (1) public class Main1 { public static void main(String[] args) { String str[] = new String[] { new String("itiban"), new String("niban"), new String("sanban"), }; for (int i = 0; i < str.length; i++ ) { System.out.println(str[i]); } } } (2) public class Main2 { public static void main(String[] args) { String str[] = { new String("itiban"), new String("niban"), new String("sanban"), }; for (int i = 0; i < str.length; i++ ) { System.out.println(str[i]); } } } なお、私の環境は以下の通りです。 OS: Microsoft Windows XP Professional SP2 java: java version "1.4.2_13" 検索エンジンで"配列 オブジェクト java"を検索しましたが、 解決に役立つ情報は見つかりませんでした。

    • ベストアンサー
    • Java
  • 簡単な配列の作り方

    やりたいことがあるのですが、原始的なやり方しか思いつきません。 簡単な方法があればご教授願いたく思い質問いたしました。 よろしくお願いします! <やりたいこと> 明細行が5件ありまして、それぞれの行に有効かどうかフラグがある。 5件のうち有効になっている数だけの配列を作成する。 --------------------------------------------- 例1)1,2,3,4,5のうち2,3,5の3行が有効の場合   String[] str = String[]{2,3,5} 例2)1,2,3,4,5のうち4の1行が有効の場合   String[] str = String[]{4} --------------------------------------------- <現在やっていること> // 有効行の判断用 private boolean yukoFlg1 = false; private boolean yukoFlg2 = false; private boolean yukoFlg3 = false; private boolean yukoFlg4 = false; private boolean yukoFlg5 = false; // 有効行の数 private long yukoCnt = 0; /** * 該当行分の配列にする String[] * @param str 配列にしたい値 */ public String[] setStrArray ( String str1, String str2, String str3, String str4, String str5) throws Exception { String[] result = null; // 有効行の数が1の場合 if (yukoCnt == 1) { if (yukoFlg1) { result = new String[]{str1}; } else if (yukoFlg2) { result = new String[]{str2}; } else if (yukoFlg3) { result = new String[]{str3}; } else if (yukoFlg4) { result = new String[]{str4}; } else { result = new String[]{str5}; } // 有効行の数が2の場合 } else if (yukoCnt == 2) { if (yukoFlg1) { if (yukoFlg2) { result = new String[]{str1, str2}; } else if (yukoFlg3) { result = new String[]{str1, str3}; } else if (yukoFlg4) { result = new String[]{str1, str4}; } else { result = new String[]{str1, str5}; } } else if(yukoFlg2) { if (yukoFlg3) { result = new String[]{str2, str3}; } else if (yukoFlg4) { result = new String[]{str2, str4}; } else { result = new String[]{str2, str5}; } } else if (yukoFlg3) { if (yukoFlg4) { result = new String[]{str3, str4}; } else { result = new String[]{str3, str5}; } } else { result = new String[]{str4, str5}; } // 有効行の数が3の場合 } else if (yukoCnt == 3){ if (yukoFlg1) { if (yukoFlg2) { if (yukoFlg3) { result = new String[]{str1, str2, str3}; } else if (yukoFlg4) { result = new String[]{str1, str2, str4}; } else { result = new String[]{str1, str2, str5}; } } else if (yukoFlg3) { if (yukoFlg4) { result = new String[]{str1, str3, str4}; } else { result = new String[]{str1, str3, str5}; } } else { result = new String[]{str1, str4, str5}; } } else if (yukoFlg2) { if (yukoFlg3) { if (yukoFlg4) { result = new String[]{str2, str3, str4}; } else { result = new String[]{str2, str3, str5}; } } } else { result = new String[]{str3, str4, str5}; } // 有効行の数が4の場合 } else if (yukoCnt == 4) { if (!yukoFlg1) { result = new String[]{str2, str3, str4, str5}; } else if (!yukoFlg2) { result = new String[]{str1, str3, str4, str5}; } else if (!yukoFlg3) { result = new String[]{str1, str2, str4, str5}; } else if (!yukoFlg4) { result = new String[]{str1, str2, str3, str5}; } else { result = new String[]{str1, str2, str3, str4}; } // 有効行の数が5の場合 } else { result = new String[]{str1, str2, str3, str4, str5}; } return result; }

    • ベストアンサー
    • Java
  • ファイルから一行を読み込み配列に格納したい

    すみません、初心者です。Javaでテキストファイルから一行の文字列を読み込み、Stringの配列に格納したいと思っています。具体的には、マシンの/tmp/test.txtを読み込み、空白行は無視して格納したいです。ウェブを参考にして、以下のようには出来たのですが、最初にStringの配列を20個宣言しており、これをどうにかテキストファイルの行(マイナス空白行)の数だけ宣言させたいです。(理由はファイルによっては想定以上の個数の場合も有り得ますし、余分なメモリを使用することになるのと、後からこの配列を使用しやすい、といった諸々で。。)以下のコードをどのように変えると実現出来るかご教示頂けませんでしょうか。 (一行あたりの文字列はつながっており、空白が間に入る事はありません) import java.io.*; public class test { public static void main(String[] args) throws Exception { int i=0; String[] str = new String[20]; FileReader fr = new FileReader("/tmp/test.txt"); StreamTokenizer st=new StreamTokenizer(fr); while(st.nextToken()!=StreamTokenizer.TT_EOF) { System.out.println(st.sval+" "); str[i]=st.sval; i++; } fr.close(); } } (test.txtが以下の場合) ----------------------- fdjosa djsoafdjfdajof jsoafds fdsaoofdafd fdjso fjds ----------------------- (配列は以下になることを想定) str[0]=fdjosa str[1]=djsoafdjfdajof str[2]jsoafds str[3]=fdsaoofdafd str[4]=fdjso str[5]=fjds (*配列数であるstr.lengthは6)

    • ベストアンサー
    • Java
  • ActionScriptで配列をクリアする方法を教えてください。

    ActionScriptで、オブジェクトを格納した配列をクリアする正しい方法を教えてください。 具体的には、 ・new Array() で配列を生成する。 ・new Object() で生成したオブジェクトを配列に格納する。 ・配列の中身を処理したあと、配列を一度クリアする。 ・配列に別のオブジェクトを格納する。 ような処理をしたいのですが、メモリリークを起こさずに配列をクリアするにはどうしたらいいでしょうか? 例えば、イメージはこんな感じです。(意味のないコードですが) // 配列の生成 var arr = new Array(); // 配列にオブジェクトを格納 for (var i = 0; i < 5; i++) { var obj = new Object(); obj.num = i; } // 配列のクリア arr.length = 0; // クリアした配列に別のオブジェクトを格納 for (var i = 0; i < 5; i++) { var obj = new Object(); obj.num = i * 2; } 上記のコードで、arr.length = 0; で配列をクリアしていますが、これで配列に格納されたオブジェクトが確保したメモリがすべて解放されるでしょうか? あるいは、配列の内容がなくなるまで pop() 等で取り出す等の処理をする必要があるでしょうか? 以上よろしくお願いします。

    • ベストアンサー
    • Flash
  • 配列について

    string[] array = new string[200]; というように、arrayという配列を宣言して、そこに CheckBox.Textを入れていきたいんですが、 stringを暗黙的にstring[]に変えれません。というようなエラーがでます。 やっぱり、こんなふうにテキストを配列に入れることは無理なんでしょうか?? 初心者であんまり分からなくて、文章が分かりづらいと思いますが、アドバイスお願いします(><)

  • ActionScriptでクラスの配列

    ActionScript3をちょっと触っているのですが、 Stringや独自クラスの配列の変数を宣言する 事は出来ないのでしょうか? var str[]:String; みたいな。 Array()を介さないとダメなのでしょうか? とすると、Array()の中が必ずStringだけとは 限らない状況に陥りそうな気がするのですが・・・。 実現方法をご教示下さい。

    • ベストアンサー
    • Flash
  • if文内の二次元配列の設定方法について

    if文内の二次元配列の設定方法について 区分の内容によって2つのクラスを呼び分けていたのですが、今回そのクラスを統合しようとしています。 そこで、2つのjavaソースを統合するにあたり、ソース内で使用している二次元配列の内容を区分によって書き換えたいのですが、 if文内に記述するため、その変数の有効範囲がif文内だけになってしまいます。 クラス全体でその配列を参照できるようにするにはどのように記述すればよいのでしょうか? <統合前> Test1.java public class Test1 { private static final String[][] LST = {{3,0,0},{0,0,1},{0,0,1}}; public void initialize() { System.out.println(LST[0][0]); } ⇒【実行結果】3 Test2.java public class Test2 { private static final String[][] LST = {{2,0,0},{0,0,1},{0,0,2},{0,0,3}}; public void initialize() { System.out.println(LST[0][0]); } ⇒【実行結果】2 上記2つのファイルを統合し、区分によって二次元配列の内容を設定する。 <統合案1> Test1.java public class Test2 { private String[][] LST; public void initialize() { if (kubun == 1) { String[][] LST = {{3,0,0},{0,0,1},{0,0,1}}; }else{ String[][] LST = {{2,0,0},{0,0,1},{0,0,2},{0,0,3}}; } System.out.println(LST[0][0]); } ⇒【実行結果】NullExceptionが発生してしまいます。 <統合案2> public class Test2 { private String[][] LST; public void initialize() { if (kubun == 1) { LST = {{3,0,0},{0,0,1},{0,0,1}}; }else{ LST = {{2,0,0},{0,0,1},{0,0,2},{0,0,3}}; } System.out.println(LST[0][0]); } ⇒【実行結果】コンパイルエラーが発生してしまいます。(式の開始が不正です。) ※kubunが1のときと、それ以外のときで作成される二次元配列の要素数は異なります。 ※kubunの内容によって、一度二次元配列の内容を設定してしまえば、あとは同じ内容のままです。 最初の変数の宣言の仕方、二次元配列の内容設定の仕方等、 どのようにすればよいかご教授よろしくお願い致します。

    • ベストアンサー
    • Java
  • staticなフィールドをstaticじゃないメソッドで使うには?

    いつもお世話になっています。よろしくお願いします。 javaで、staticなメインメソッドからも、staticじゃないメソッドからも1つの メンバ変数(フィールド)を処理したいと思います。 private static String nr; というフィールドを宣言しました。 (staticであるmainメソッドの中で使えるようにstaticで宣言しようと思いました。) 次に、 private void Kensaku() { このstaticではないメソッドの中でString nrを使って処理を行いたいです。 } 初歩の初歩なことを質問してすみませんが、調べても分かりませんでした。 どうか、よろしくお願いします。

    • ベストアンサー
    • Java
  • 配列のオフセットおよび長さが範囲を超えている

    C#のASP.NETで運用していますが、 static SortedListを使って、メモリに保持しておいて、 レスポンスを早くするようにしていますが、 if (_SortedList.ContainsKey(str)) return (ArrayList)_SortedList[str]; とデータを取得しようとすると、 なぜかインデックスが重複しているわけでもないのに、 「配列のオフセットおよび長さが範囲を超えているか、カウンタがソース コレクションのインデックスから最後までの要素の数より大きい値です。」 とエラーが発生します。 なぜエラーとなるのでしょうか? またASP.NETでメモリ上に保持する方法は static以外にあるのでしょうか?