- - PR -
taglibでMapにアクセス
投稿者 | 投稿内容 | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2006-07-11 00:30
ちょっと、意味のわからない現象が出ています。
だいぶ省略しますが、このようなクラスを定義します。 public class Hoge { private Map data = new HashMap(); public Map getTada() { return this.data; } } このdataにtaglibでアクセスします。 <c:out value="${hoge.data['key'].value}" /> で、正しい値が表示されます。 しかし、クラスの定義を下記のようにすると、 public class Hoge extends HashMap { 上記taglibでの表示結果は、 空文字列になってしまいます。 public class Hoge implements Map { としても同様に空文字列になってしまいます。 dataという変数名がいけないのかと思い、 予約語になりそうにない名前をつけてもダメでした。 どうしてでしょうか? どなたか、見当が付く方がいらっしゃいましたら 教えてください。 | ||||||||||||||||||||||||
|
投稿日時: 2006-07-11 11:55
よく状況がわからないのですが、
このように変更した後も、
このようにして表示しようとしている、ということですか? クラス定義を変えた後もgetDataというメソッドは存在しているのですか? | ||||||||||||||||||||||||
|
投稿日時: 2006-07-11 12:02
コメントありがとうございます。
変更したのは、「 extends HashMap 」をつけただけで、 getData()メソッドも存在します。 よろしくお願いいたします。 | ||||||||||||||||||||||||
|
投稿日時: 2006-07-12 22:46
アクセスの仕方を間違えているに一票。
${hoge.data['key'].value}がそもそも何にアクセスしているかですが…。 まず、${hoge}はHttpServletRequest型の暗黙オブジェクトrequestに "hoge"というキーでsetAttributeされているオブジェクトへのアクセスです。 値を設定しているServlet側の処理が書かれていないので憶測ですが
とでもなっているのでしょう。 ${hoge.data['key']}では、このhogeに対して getData()メソッド(getTada()と宣言しているのはtypoですかね?) を呼び出して取得したMapに対しget("key")を呼び出して 得たオブジェクトにアクセスしています。 ${hoge.data['key'].value}ではさらにそのオブジェクトの getValue()メソッドで値を取得しているわけです。 この上記の過程のどこまで正しく動いて、どこから正しくないのかを 探ればバグの原因がつかめるのではないでしょうか。 私の予測ではHoge自身をMapにした際に
としているなどのミスがあるのではないか…。 深い階層を持つデータを扱う際はよくやるミスですが、 EL式でアクセスする場合はエラーにならないので バグがわかりにくいかもしれませんね。 | ||||||||||||||||||||||||
|
投稿日時: 2006-07-13 09:45
ELではMapに対し通常のプロパティ名と同様の記法でアクセスできる仕様を提供しています。Mapを実装したHogeに対する
hoge.data['key'].value の意味は、まず、 hoge.get("data"); となります。get("data")の戻り値がnullなので途中の処理が省略されて、空文字列が返されているのでしょう。 | ||||||||||||||||||||||||
|
投稿日時: 2006-07-13 10:49
上記指摘の動きがちょっと記憶になかったので調べてみました。 http://java.sun.com/products/jsp/syntax/2.0/syntaxref207.html#1010522 言語仕様側では該当の記述がどこなのかよくわからないのですが (単に私の語学力の問題のようにおもいますけど:-P) ELのTipには該当のネタがありました。 http://java.sun.com/developer/EJTechTips/2004/tt0126.html
確かに、Mapの場合は"."の後ろのプロパティを文字列リテラルとして キーとして扱うという動きをするようですね。 いやはや、失礼いたしました。 | ||||||||||||||||||||||||
|
投稿日時: 2006-07-13 11:35
皆様、ありがとうございます。
状況が理解できました。 まず、現象を起こす最も簡単なサンプルを提示します。 ■Hoge.java
■Servlet(こちら、Springを使っています)
■JSP
これで、"value"と表示されます。 Hogeクラスのシグニチャを public class Hoge extends HashMap<String, Object> { に変更すると、"value"は表示されなくなります。 そこで、
これを踏まえ、Hoge.javaを変更したら表示されるようになりました。 変更パターン1:コンストラクタでdataをput()
変更パターン2:getメソッドをオーバーライド
#なんで、HashMap#get()メソッドのシグニチャは #V get(Object key) なの? #V get(K key) じゃないんだろう? しかし、問題があります。 genericsを使って書いたのはそのためなのですが、 実際のHogeクラスのシグニチャは、 public class Hoge extends HashMap<String, String> { なのです。 よって、 this.put("data", this.data); も return this.data; もエラーです。 これを回避する方法を考え中です... #せめて、HashMap#get()メソッドのシグニチャが #Object get(K key) か Object get(Object key) #ならなぁ... [ メッセージ編集済み 編集者: Jumpin' Jack Flash 編集日時 2006-07-13 11:36 ] [ メッセージ編集済み 編集者: Jumpin' Jack Flash 編集日時 2006-07-13 11:37 ] | ||||||||||||||||||||||||
|
投稿日時: 2006-07-13 22:04
なぜそんなことをしないといけないのでしょうか? 背景が見えませんが、V get(Object key)ではなく、 Object get(Object key)だったらいいな、とおっしゃってますか? もし、単にvalue側をObject型として扱いたいのであれば HashMap<String, Object>とすればよいのではないですか? valueの型を可変にしたいのであれば、 public class Hoge<V> extends HashMap<String, V> でよいでしょうし。 extends HashMapしている点も含めて、データの構造の設計が 危ういように思えますが…。 |