Android Studio 進捗報告 14日目 | JavaのArrayListやインスタンスの動きが分かってなかった
IT専門学生のふじさわです。
最近、相変わらずAndroid Studio(Java)を触っていますが、インスタンスを格納するArrayListの動きを勘違いしていたのでログを残します。
ArrayListとは?
改めて言うのもなんですが、簡単に言えば任意の型の可変長配列を作れるクラスです。(この認識がもう間違っているかもしれません。)
ArrayList<型> 変数名 = new ArrayList<>();
こんな形で、指定した<型>の配列を作ります。型にはクラスが入るので、intとかはラッパークラスのIntegerで指定する必要があります。
ここでは当然、自分で定義したクラスも扱えます。今回はその扱い方にミスがありました。
今回やりたかったこと
データベースの1レコードごとにインスタンスとして用意し、そのインスタンスをArrayListに格納したかったので、こんな感じで作成しました。
(※ 実際コードとは異なります。また、DBの処理は簡略化しています。)
・DB > Itemテーブル
カラム:int id, String name
id には 1 ~ 10、name には a ~ j が入ってる。
・Itemクラス(自分で定義したクラス)
プロパティ:int id, String name
メソッド:各 getter, setter のみ
Item item = new Item();
ArrayList<Item> itemArray = new ArrayList<>();
while(テーブルの1レコードずつ最後まで){
int id = テーブルのカラム"id";
String name = テーブルのカラム"name";
// DBの値をインスタンスにセット
item.setId(id);
item.setName(name);
// 値をセットしたインスタンスを格納
itemArray.add(item);
}
私の予想では、itemArray を出力するとテーブルの中身通りに
id: 1, name: a
id: 2, name: b
id: 3, name: c
・
・
と続くと思っていたのですが、実際は
id: 10, name: j
id: 10, name: j
id: 10, name: j
・
・
みたいにitemArrayの中身が最後の値で全部上書きされちゃったんですよね。
原因と解決方法
で、この原因は、itemArrayの(0)から(9)まで全部にwhileの外で生成した同一インスタンスが重複して格納されていて、そのインスタンスのプロパティを変更しているだけに過ぎないからでした。(多分)
つまり、インスタンスの配列を作るなら毎回別の参照先を持ったインスタンスを新たに生成して、それらを格納する必要があるわけです。
こう書くと至極当たり前の話なのですが、自分の中の知識や概念が曖昧なままコーディングしているためこのようなミスが発生したのだと思います。
もっと根本的な理解をしないといけないな、と反省しました。
正しく動かすにはこのように書く必要があります。
ArrayList<Item> itemArray = new ArrayList<>();
while(テーブルの1レコードずつ最後まで){
int id = テーブルのカラム"id";
String name = テーブルのカラム"name";
// 毎回新しいインスタンスを生成
Item item = new Item();
// DBの値をインスタンスにセット
item.setId(id);
item.setName(name);
// 値をセットしたインスタンスを格納
itemArray.add(item);
}
きっとこれでもまだまだ粗いのだとは思いますが、それはこれから洗練させていきたいです。
※ 追記
ネットで調べて新たに知ったのですが、
ArrayList<Item> itemArray = new ArrayList<>();
このようなコードは密結合になってしまうため、
List<Item> itemArray = new ArrayList<>();
上記のようにitemArrayはListで定義して、インスタンス生成にあたって実装クラスのArrayListでnewすることで、結合度を疎にすることも重要だそうです。
以上です。
まだまだ技術力を上げるために頑張るぞ!
記事をご覧いただきありがとうございます! サポートしていただいたお気持ち以上に、noteをはじめいっぱい頑張ります!