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

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

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

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

Q&A

解決済

3回答

4570閲覧

ジェネリクスでオブジェクトを取得しメンバ一覧を取得したい

lupus_dingo

総合スコア257

Java

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

0グッド

0クリップ

投稿2015/03/02 15:45

あるメソッドの仮引数を定義する際に、実際に値が引数に代入されないと型がわからない場合、ジェネリクスという方法を使うと仮引数の型を固定せずに実装できるようですが、その正しい表記を教えて下さい。
仮引数の部分を<T><T extends Base>や<?>などのように指定してみたのですが、構文エラーになります。

やりたいことは以下のようなイメージで、引数のメンバー変数名とその値をすべて取得することです。

private Map<String, V> getMembers(<T extends Base> obj){ // 引数の型は不定
HushMap <String, V > map = new HushMap<String, V >(); // 値の型は不定
for (Field field : obj.getClass().getDeclaredFields(){
field.setAccessible(true);
map.put(field.getName(), field.get(obj) ) ;
}
return map;
}

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

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

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

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

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

guest

回答3

0

型が揃っていないのであれば,ハッシュマップを使うよりBundleのほうが使い勝手がいいのではないでしょうか?

Android-Bundle-Qiita

投稿2015/03/06 15:27

swordone

総合スコア20649

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

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

lupus_dingo

2015/03/09 09:20

回答ありがとうございます。Bundle初めて聞きました。 調べてみます。
guest

0

ベストアンサー

まず、仮型引数を使わない場合から考えてみましょう。
こんな感じになります。

lang

1static Map<String, Object> getMembers(Object obj) { 2 Map<String, Object> map = new HashMap<>(); 3 for (Field field : obj.getClass().getDeclaredFields()) { 4 field.setAccessible(true); 5 try { 6 map.put(field.getName(), field.get(obj)); 7 } catch (IllegalArgumentException | IllegalAccessException e) { 8 e.printStackTrace(); 9 } 10 } 11 return map; 12}

これにT extends BaseVを導入すれば良いと思いますが、逆に質問です。

Tのフィールドは全て同じクラスということでしょうか?
field.get(obj)の戻り値はObjectになりますが、どのようにVに変換しますか?
ObjectVの変換は、VStringならばtoStringでできますが、それ以外の場合はどのように変換するイメージですか?


(追記)

コンバーターの機能をBaseクラスに持たせるようにします。コンバーターはサブクラスごとに実装する必要があります。

lang

1abstract class Base<V> { 2 3 abstract V convert(Object o); 4 5} 6 7class Foo extends Base<Integer> { 8 9 int x = 3; 10 int y = 2; 11 String z = "5"; 12 13 @Override 14 Integer convert(Object o) { 15 if (o instanceof Number) { 16 return ((Number)o).intValue(); 17 } 18 if (o instanceof CharSequence) { 19 try { 20 return Integer.parseInt(o.toString()); 21 } catch (NumberFormatException e) { 22 e.printStackTrace(); 23 } 24 } 25 return 0; // デフォルト値 26 } 27 28} 29 30public final class App { 31 32 static <V, T extends Base<V>> Map<String, V> getMembers(T obj) { 33 Map<String, V> map = new HashMap<>(); 34 for (Field field : obj.getClass().getDeclaredFields()) { 35 field.setAccessible(true); 36 try { 37 map.put(field.getName(), obj.convert(field.get(obj))); 38 } catch (IllegalArgumentException | IllegalAccessException e) { 39 e.printStackTrace(); 40 } 41 } 42 return map; 43 } 44 45 public static void main(String[] args) { 46 System.out.println(getMembers(new Foo())); 47 // => {z=5, y=2, x=3} 48 } 49 50}

投稿2015/03/03 01:36

編集2015/03/03 13:16
argius

総合スコア9388

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

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

lupus_dingo

2015/03/03 05:37

仮引数TにはBaseという親クラスから派生したいずれかのクラスのオブジェクトが渡されます。 確かに、field.get(obj)としたときの戻り値の型変換の考慮が抜けてました。fieldはint、String、Dateなどいろんな値が入りますが、処理のイメージがつきません。そもそもObjectからこのような型変換は可能なのでしょうか?
argius

2015/03/03 06:23

>Objectからこのような型変換 追記しました。
swordone

2015/03/03 12:58

そんなまどろっこしいことせずとも,ジェネリクスで宣言したVを使って (V)object; のようにキャスト式で変換できますよ
argius

2015/03/03 13:21

swordoneさん ちょっと追記したんですが、zのような場合にはキャストでは問題があります。格納はできますが、取り出すときにIntegerのキャストに失敗してしまいます。
lupus_dingo

2015/03/05 23:27

回答ありがとうございます。 今手元に環境がないので調べられないのですが、 コンバートの戻り値がinteger型なのは、mapの値は常にintであると仮定した場合でしょうか?DateやStringのフィールドもある場合はそれもジェネリクスで実装する必要があるでしょうか?
argius

2015/03/05 23:44

同じクラスのフィールドにintやDateやStringが混在していた場合、何らかの形にコンバートしないのであればMap<String, V>のVはObjectにせざるを得ません。なのでVにする意味はあまりないと考えているのですが如何でしょう。
lupus_dingo

2015/03/09 09:27

回答ありがとうございます。 なんだかObject配列を戻り値としたフィールドの値を取得するメソッドを作成してみたら望むことができました。いろいろアドバイスいただいたのにすみません。 でも勉強になりました。
guest

0

とりあえず、メソッドの宣言と変数の宣言のみですが...

lang

1private <V extends Base> Map<String, V> getMembers(V obj) { 2 Map<String, V> map = new HashMap<>(); 3 return map; 4}

非常に参考になるサイトがありますので、貼っておきます。

参考: Java総称型メモ(Hishidama's Java Generics Memo)

投稿2015/03/02 16:03

ryunix

総合スコア1656

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

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

lupus_dingo

2015/03/03 05:37

回答ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問