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

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

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

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

Q&A

解決済

1回答

11547閲覧

getMethod、invokeの第2引数について

XCUBE

総合スコア101

Java

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

0グッド

1クリップ

投稿2016/02/23 02:33

編集2016/02/23 06:18

こんなクラスがあったとします。

java

1class Test { 2 private Double A; 3 private Integer B; 4 private String C; 5 6 public void setTest(Double arg) { A=arg; } 7 public void setTest(Integer arg) { B=arg; } 8 public void setTest(String arg) { C=arg; } 9}

このクラスをリフレクションを使ってスマートに設定する関数を作ろうとしたのですが
getMethodの<<1>>、invokeの<<2>>の第2引数をどう書いていいのかわからず試行錯誤しております。
<<1>>はvalueを元にgetClass()を渡してみましたがNoSuchMethodExceptionのエラーとなります。

java

1Test test = new Test(); 2SetFunc(test, new Double(123.45)); 3SetFunc(test, new Integer(123)); 4SetFunc(test, new String("ABC")); 5 6public void SetFunc(Test cls, Object value) { 7 Method method = cls.getClass().getMethod("setTest", <<1>>); 8 method.invoke(cls, <<2>>); 9}

そもそもこのような場合はSetFuncのvalue引数のクラスによって振り分けるなど
しなければ実現できないのでしょうか?

ご教示の程、よろしくお願い致します。


追記

java

1 2class Test { 3 private float D; 4 private Double A; 5 private Integer B; 6 private String C; 7 8 public void setTest(float arg) { D=arg; } // float型が引数 9 public void setTest(Double arg) { A=arg; } 10 public void setTest(Integer arg) { B=arg; } 11 public void setTest(String arg) { C=arg; } 12} 13

java

1public class JavaApp { 2 3 public static void main(String[] args) throws Exception { 4 Test test = new Test(); 5 SetFunc(test, 123.4f); 6 SetFunc(test, new Double(123.45d)); 7 SetFunc(test, new Integer(123)); 8 SetFunc(test, new String("ABC")); 9 } 10 11 public static void SetFunc(Test cls, Object value) throws Exception { 12 Method method = cls.getClass().getMethod("setTest", value.getClass()); 13 method.invoke(cls, value); 14 } 15} 16 17

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

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

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

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

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

guest

回答1

0

ベストアンサー

SetFunc メソッドがおかしいです。
以下のようにすればいけるのではないでしょうか?
あとメソッド名は小文字はじまりが基本ですので、setFunc にすべきですね。

java

1public void SetFunc(Test cls, Object value) throws Exception { 2 Method method = cls.getClass().getMethod("setTest", value.getClass()); 3 method.invoke(cls, value); 4}

そもそも、これぐらいならコンストラクで設定するか、セッターで設定しても労力変わらない気がします。

java

1// これも 2SetFunc(test, new Double(123.45)); 3SetFunc(test, new Integer(123)); 4SetFunc(test, new String("ABC")); 5 6// これも 7new Test(new Double(123.45), new Integer(123), "ABC"); 8 9// これも労力同じでは? 10test.setA(new Double(123.45)); 11test.setB(new Integer(123)); 12test.setC("ABC");

以下のような理由で、あまりリフレクションはおすすめしません。
・自分以外の人がコードを理解するのが難しい
・コンパイラでエラーを検出できない。全て実行時エラー
・IDEのリファクタリング機能が及ばない。例えば setTest メソッドの名前が変わったら終わり。
・デバッグがしづらく、バグの調査に苦労する
・多用しなければ問題ないレベルだが、通常のコードよりは数倍遅い

フレームワークを作る際には、リフレクションは必須ですが、
その場合、フレームワークの使用者からはカプセル化されてて意識することもないですからね。

###追記

Java

1public class Main { 2 public static void main(String[] args) throws Exception { 3 Test test = new Test(); 4 SetFunc(test, new Double(123.45)); 5 SetFunc(test, new Integer(123)); 6 SetFunc(test, new String("ABC")); 7 8 System.out.println(test); 9 } 10 11 public static void SetFunc(Test cls, Object value) throws Exception { 12 Method method = cls.getClass().getMethod("setTest", value.getClass()); 13 method.invoke(cls, value); 14 } 15} 16 17class Test { 18 private Double A; 19 private Integer B; 20 private String C; 21 22 public void setTest(Double arg) { 23 A = arg; 24 } 25 26 public void setTest(Integer arg) { 27 B = arg; 28 } 29 30 public void setTest(String arg) { 31 C = arg; 32 } 33 34 @Override 35 public String toString() { 36 return new StringBuilder("A = ").append(A).append(System.lineSeparator()) 37 .append("B = ").append(B).append(System.lineSeparator()) 38 .append("C = ").append(C).append(System.lineSeparator()) 39 .toString(); 40 } 41}

投稿2016/02/23 02:53

編集2016/02/23 03:28
root_jp

総合スコア4666

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

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

XCUBE

2016/02/23 03:13 編集

value.getClass()は試しましたがNoSuchMethodExceptionとなります。 ここまでですでに数時間の調査、試行錯誤をしており、労力などの問題ではなく 技術的にできないものかというところで探究心もありご質問させていただきました。 いろいろとご指導していたたことに感謝しております。
root_jp

2016/02/23 04:25 編集

なるほど。探究心からですか。それは失礼しました。 僕の方でも試してみましたけど、動くようですよ。 参考までに全ソースを追記してみました。
XCUBE

2016/02/23 06:04

具現化したコードまで添付いただきましてありがとうございます。 確かに動きました! 最初に私が投稿したTestクラスはビューアの方々に解りやすく説明するために 最小限のものとして書いたもので、本当にお手間をお掛けして申し訳ないです。 実際に試していたコードではクラスではなくfloat型を引数としたsetメソッド public void setTest(float arg) があり、これだとSetFuncでfloat型を渡してもObjectにキャストされて、 getClass()の結果がjava.lang.FloatになるためNoSuchMethodExceptionと なったことが原因だとお蔭様で気づくことができました。 このような場合 getMethodの引数としてfloat.classをObject valueから求めたり、 invokeの引数としてfloat型に戻したり汎用的に使えるようにすることは難しい のでしょうか?
root_jp

2016/02/23 06:27

プリミティブ型を汎用的にするのは、たぶん無理だと思います。 Javaのめんどくさいところです。。。 過去に見たいくつかのフレームワークのソースも プリミティブの数だけの if と Object で分けて書かれていました。
XCUBE

2016/02/23 07:03 編集

そうですか。これで諦めがつきました。 データ型・・・いやプリミティブ型の種類も限られているので 全てに対応することもそう大変ではなさそうということもハッキリしました。 「プリミティブ型」という言葉も知り、大変勉強になりました。 実際にやりたかったことはクラスの属性をgetMethods()によってgetメソッドを取得し、 そこから得られた値を変更したものを、setメソッドで更新するための手段として 考えていました。 予めわかっているメソッドなので一つ一つgetとsetを書くのも悪くないのですが、 数が多いのと引数の型がバラバラだったのでリフレクションでこじんまりと 書けないかというところから深追いしておりました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問