- PR -

フィールド変数を取得する

1
投稿者投稿内容
kei111
会議室デビュー日: 2005/03/03
投稿数: 10
投稿日時: 2005-03-22 16:02
こんにちは

もともと
String NAME[0] = "A";
String VALUE[0] = "1";
String NAME[1] …
と定義されていたクラスからインターフェースを参照するように変更したのですが、

そのクラスに変数名を引数に渡せばその値を返すようにするのはどうしたらいいでしょうか?

引数にフィールド変数の名前を渡し、戻り値がその参照している値を返すmethod。
イメージ的には
クラス名がTestとするとTestクラスに以下のようなメソッドがほしいです。
public String getVariable(String name) {
return Test.name;
}
これでは当然できませんが、どうすればいいか分かりません。

よろしくお願いいたします。
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2005-03-22 16:08
このテのことを実現するにはリフレクションと呼ばれる API 群を使います。
このスレッドが役に立つと思います。
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=19937&forum=12&3
実行時の方やメソッド名、プロパティ名などをコンパイル時に決定できないフレームワークなどでは必須の機能ですが、うまく使わないと予期せぬ実行時例外が頻発します。
ご要望のことは Map を使うだけで済むのかもしれませんのでまずは通常の(リフレクションを使わない)プログラミングで実現できないか検討することをお勧めします。
kei111
会議室デビュー日: 2005/03/03
投稿数: 10
投稿日時: 2005-03-22 16:42
さっそくのお返事ありがとうございました。
リフレクションに関しては知りませんでしたので
フィールド変数にHashMapを定義して
コンストラクタにmap.put()で値を格納することでとりあえずできました。
ただ、mapに何十個もキーとマッピングしているとなんか結構パフォーマンスに響いてくるかも知れないなと思いました。

どうもありがとうございました。
ふーばー
大ベテラン
会議室デビュー日: 2003/06/05
投稿数: 163
投稿日時: 2005-03-22 16:59
引用:

kei111さんの書き込み (2005-03-22 16:42) より:
ただ、mapに何十個もキーとマッピングしているとなんか結構パフォーマンスに響いてくるかも知れないなと思いました。



そういうことは「ハッシング」について勉強してから言いましょうね。
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2005-03-22 17:15
>ただ、mapに何十個もキーとマッピングしているとなんか結構パフォーマンスに響いてくるかも知れないな
>と思いました。
なるほど。でもリフレクションをつかっても結局インスタンスに福間られるプロパティのリストから情報をとってくるわけですから根本的な処理はかわらないですよね。
パフォーマンスについてはまず気にしないことです。パフォーマンスを低下させる絶対やってはいけないコーディング、みたいのはあるかもしれませんが、多くの場合はまず動くものを作ることが大事です。
遅いことに気が付いてからボトルネックを探してチューニングするほうが効率的です。
#もちろん、気になったら都度実験をして速度を確かめてみるのも良いですね
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2005-03-22 17:22
蛇足ですが・・・

リフレクションよりMapの方が参照に関わるコストが軽微になると思います。

Mapは通常、キーのインスタンスのハッシュ値を元に
ハッシュ表から値のインスタンスを検索していますので、そんなに遅くはありません。

リフレクションはフィールドやメソッドを検索する為に
実装によって違いがありますが、バイトコードの解析が行われますので、
Mapよりはコストがかかってしまうでしょう。内部ではキャッシュされると思いますが。

で、試してみました。
コード:
package test;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class Test {
	static class A {
		String a = "a";
		String b = "b";
		String c = "c";
		String d = "d";
		String e = "e";
		String f = "f";
		String g = "g";
		String h = "h";
		String i = "i";
		String j = "j";
		String k = "k";
		String l = "l";
		String m = "m";
		String n = "n";
		String o = "o";
		String p = "p";
		String q = "q";
		String r = "r";
		String s = "s";
		String t = "t";
		String u = "u";
		String v = "v";
		String w = "w";
		String x = "x";
		String y = "y";
		String z = "z";
	}
	static class B {
		Map map = new HashMap();
		B() {
			map.put("a", "a");
			map.put("b", "b");
			map.put("c", "c");
			map.put("d", "d");
			map.put("e", "e");
			map.put("f", "f");
			map.put("g", "g");
			map.put("h", "h");
			map.put("i", "i");
			map.put("j", "j");
			map.put("k", "k");
			map.put("l", "l");
			map.put("m", "m");
			map.put("n", "n");
			map.put("o", "o");
			map.put("p", "p");
			map.put("q", "q");
			map.put("r", "r");
			map.put("s", "s");
			map.put("t", "t");
			map.put("u", "u");
			map.put("v", "v");
			map.put("w", "w");
			map.put("x", "x");
			map.put("y", "y");
			map.put("z", "z");
		}
	}
	public static void main(String[] args) throws Exception {
		String[] keys = new String[] { "a", "b", "c", "d", "e", "f", "g", "h",
				"i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
				"u", "v", "w", "x", "y", "z" };
		A a = new A();
		System.out.println(System.currentTimeMillis());
		for (int i = 0; i < 100000; i++) {
			for (int j = 0; j < keys.length; j++) {
				a.getClass().getDeclaredField(keys[j]);
			}
		}
		System.out.println(System.currentTimeMillis());
		B b = new B();
		for (int i = 0; i < 100000; i++) {
			for (int j = 0; j < keys.length; j++) {
				b.map.get(keys[j]);
			}
		}
		System.out.println(System.currentTimeMillis());
	}
}


環境によって違いますが、上記のソースをj2se1.4.2_06/Eclipse3.0.1で実行した場合、
リフレクションの方がMapより平均19倍時間がかかっていました。
1

スキルアップ/キャリアアップ(JOB@IT)