質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

Q&A

解決済

2回答

22391閲覧

[Java]ArrayListの中身のダウンキャストについて

rontec

総合スコア169

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

0グッド

0クリップ

投稿2015/12/17 01:48

編集2015/12/17 01:57

初歩的な質問で恐縮なのですが、javaのダウンキャストの記述で良い方法がないか悩んでいます。
とある親クラスから、複数の子クラスを継承して作っています。

java

1public class Parent { 23} 4 5@Document(collection = "child1") 6public class Child_1 extends Parent { 7} 8 9@Document(collection = "child2") 10public class Child_2 extends Parent { 11} 12 13@Document(collection = "child3") 14public class Child_3 extends Parent { 15}

それぞれ子クラスは親クラスを継承しておりますが、追加の要素やメソッドはありません。
spring bootで各childをmongoDBの各コレクションに紐付けていることから、わざわざ分けています。
そのため代入する中身を作成するメソッドは1つです。

java

1public ArrayList<Parent> make(引数) { 23}

上記のメソッドの返り値を状況次第で、Child_1・Child_2・Child_3にダウンキャストしてDBに保存する必要があります。
ここで2つ疑問がございます。

1. そもそもダウンキャストは、各要素を一つ一つ代入するしかないのでしょうか。

java

1例) 2Child_1 child_1 = new Child_1(); 3child_1.setHoge1(parent.getHoge1()); 4child_1.setHoge2(parent.getHoge2()); 5 ・・・

操作や属性が結構あるので、各childごとに上記設定をすることはさすがに手間がかかるなと感じました。
「Child_1 child_1 = (Child_1)parent;」だと案の定ClassCastExceptionになりました。


2. ArrayList内のクラスのキャストで、リーダブルな記述方法はないでしょうか。
現在は都度以下のように繰り返しで要素を逐次変換しかないのかなと考えております。

java

1ArrayList<Parent> parentList = make(); 2 3ArrayList<Child_1> CastList = new ArrayList<>(); 4for (Parent parent : parentList) { 5 ダウンキャスト処理 6 CastList.add(); 7} 8 9ArrayList<Child_2> CastList = new ArrayList<>(); 10for (Parent parent : parentList) { 11 ダウンキャスト処理 12 CastList.add(); 13} 14 15ArrayList<Child_3> CastList = new ArrayList<>(); 16for (Parent parent : parentList) { 17 ダウンキャスト処理 18 CastList.add(); 19}

以上、お願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2015/12/17 02:51 編集

MongoDBの使い方を間違っている可能性はないでしょうか。使用経験が無いためググっただけの知識になりますが、 http://stackoverflow.com/a/24995698/4506703 を見る限りcollection名はアノテーションだけでなくinsert/find時に引数でも指定できるように見えます。これで解決するなら子クラスが不要になるので、ダウンキャストする必要もなくなりますよね。(一般的に、ダウンキャストしなければならない状況になった場合は、間違った実装を行っている可能性を疑うべきです。通常はそんなことをしなくて済むようにAPI設計を行うので。)
rontec

2015/12/17 03:15

アドバイスありがとうございます。 私の場合はMongoRepositoryを使用しているのですが、MongoTemplateを使用した場合はDB名を利用出来るようです。 仰られるように、MongoTemplateを使うことで無駄にクラス名を増やさないで対応出来るかもしれません。 MongoRepositoryの使用に若干固執していた節もあるので、確かに使用するライブラリを見なおした方が良いのかもしれません。 ※MongoRepositoryの方が簡単に使えるには使えるのです。 参考にさせて頂きます。
guest

回答2

0

ベストアンサー

java

1class Base { 2 int a,b,c; 3 //getter , setter, パラメタ3つ取るコンストラクタとデフォルトコンストラクタを定義 4 public <T extends Base> T downcast(Class<T> clazz) { 5 T o = clazz.newInstance(); 6 o.a = this.a; 7 o.b = this.b; 8 o.c = this.c; 9 return o; 10 } 11} 12// その他、toString を用意。メンバー変数はプリミティブなのでそのままコピーしてますが、参照の場合はちゃんとコピーしてください。 13 14

java

1// 派生クラス、例示するのは1個だけ。 2class Cb extends Base { 3 // 2つのコンストラクタの定義、 4}

java

1class Util { 2 public static <T extends Base> List<T> toDowncastList(Class<T> clazz, List<Base> list) { 3 List<T> nlist = new ArrayList<>(); 4 5 for (Base o : list) { 6 nlist.add(o.downcast(clazz); 7 } 8 return nlist; 9} 10// exception 一杯出ます、ちゃんとコーディングするように型強制させたのでこれらのruntime 例外はまず出ません。けど、throws で呼び出し側に責任押し付けて問題ないです。 11コード

使い方
List<Cb> cbs = Util.toDowncastList(Cb.class, BaseOrientedList);

ちょっとしたことなのにこんなに一杯コード書いてあげるとやっと1行で書けるようになります。
どの言語でも下処理はかわらないかと。

投稿2015/12/17 03:17

ipadcaron

総合スコア1693

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ipadcaron

2015/12/17 03:27

参照メンバーのコピーとか配列メンバーとか、階層構造を内包したメンバーとか怪しいコピーが一杯あっていちいちクローン書くのがめんどうなら、 spring の entity なんで、全てに serializable インターフェースが付いてるはず、なので、これを利用して deep copy が実質3 行くらいで書けます。 シリアル化がいかに重いのか?までは確認してません。
rontec

2015/12/17 06:33

アドバイスありがとうございます。 serializableを利用する点については、方法すら思いついていませんでした。 とりあえず最初に提示頂いた方法で解決いたしました。 今まであまり型にそれほどうるさくない言語をメインに取り扱っていたため、大変たすかりました。 いろいろ参考書なども読んでいるのですが、実際作って問題に直面しないとわからないものですね。
guest

0

データベースに関してはそれほどよく理解があるわけではないのですが、
そもそもこれに関して3つも子クラスを作る必要があるのでしょうか?

それぞれ子クラスは親クラスを継承しておりますが、追加の要素やメソッドはありません。

ということなので、親クラスに「どのデータベースのデータか?」という情報(数値など)をもたせれば済む話なのではないでしょうか?
リストを振り分ける際にその情報を元にどのリストに振り分けるかを判別すれば実現できそうな気がしますが…。


これではいけなかった場合のため、元の質問にお答えします。

  1. そもそもダウンキャストは、各要素を一つ一つ代入するしかないのでしょうか。

ここの例でダウンキャストに失敗した原因は、例えばChild_2型のものをChild_1にキャストしようとしたためです。型が合致していればダウンキャストできます。

  1. ArrayList内のクラスのキャストで、リーダブルな記述方法はないでしょうか。

あくまで私の意見ですが、instanceofを使ってみるのはどうでしょう。そもそもご提示のコードでもClassCastExceptionが出る恐れがあります。

java

1ArrayList<Parent> parentList = make(); 2ArrayList<Child_1> castList1 = new ArrayList<>(); 3ArrayList<Child_2> castList2 = new ArrayList<>(); 4ArrayList<Child_3> castList3 = new ArrayList<>(); 5 6for(Parent parent : parentList){ 7 if(parent instanceof Child_1){ 8 castList1.add((Child_1)parent); 9 } else if(parent instanceof Child_2){ 10 castList1.add((Child_2)parent); 11 } else if(parent instanceof Child_3){ 12 castList1.add((Child_3)parent); 13 } 14}

A(オブジェクト) instanceof B(参照型名)は、AがBにキャストできるときにtrueを返す演算子です。
これによって型をチェックし、合致するものを対応するリストに格納するループにしました。

投稿2015/12/17 02:13

swordone

総合スコア20649

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

rontec

2015/12/17 03:22

アドバイスありがとうございます。 > そもそもこれに関して3つも子クラスを作る必要があるのでしょうか? MongoRepositoryを使用した場合、ドメインクラスにコレクション名までアノテーションで定義することで非常に簡単にDB操作出来るため、そのようにしておりました。 --- > ここの例でダウンキャストに失敗した原因は、例えばChild_2型のものをChild_1にキャストしようとしたためです。型が合致していればダウンキャストできます。 サブクラスであれば、スーパークラスからのダウンキャストは可能ということですよね。 再度見なおしてみたのですがスーパークラスの型で作られたものを、そのサブクラスにダウンキャストしているだけなのですが、何か想定していないところで私が何かやらかしている可能性が高そうですね…。 > あくまで私の意見ですが、instanceofを使ってみるのはどうでしょう。そもそもご提示のコードでもClassCastExceptionが出る恐れがあります。 ダウンキャストにおいてinstanceofの使用が有効と他サイトでも見かけましたが、やはり安全策としても必要なのですね。 参考にさせて頂きます。
swordone

2015/12/17 08:01

> スーパークラスの型で作られたものを、そのサブクラスにダウンキャストしているだけ これは確実に例外になります。 スーパークラスのインスタンスはサブクラスの情報が入っていないため(たとえ追加要素がなくても)、キャストできません。 ダウンキャストできるのは、サブクラス型のインスタンスを「スーパークラス型として扱っている」状態のオブジェクトを、元のサブクラス型にキャストする場合です。
rontec

2015/12/24 00:49

しばらくサイトを開いていなかったため、返答が遅くなりました、失礼しました。 はじめからスーパークラスとして作っている場合、ダウンキャスト出来ないのですね。 今回の私の失敗は正にこの場合に当てはまると思います。 分かりやすいアドバイスありがとございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問