- すべての実装されたインタフェース:
InvocationHandler
EventHandler
クラスは、受信イベント・オブジェクトとターゲット・オブジェクトを含んだ単純な文を実行するメソッドを持つ、イベント・リスナーの動的生成をサポートします。
EventHandler
クラスは、開発者がBean間の接続を確立するために使用する、アプリケーション・ビルダーのような対話型ツールで使用されます。 通常、接続は、ユーザー・インタフェースBean (イベント・ソース)からアプリケーション・ロジックBean (ターゲット)に向けて確立されます。 そのなかでも、ユーザー・インタフェースからアプリケーション・ロジックを隔離するような接続は特に効果的です。 たとえば、JCheckBox
とブール値を受け付けるメソッドを接続するEventHandler
は、チェックボックスの状態を抽出し、これを直接メソッドに渡すことによって、メソッドをユーザー・インタフェース層から隔離することができます。
ユーザー・インタフェースを使ったイベントの処理方法としてより一般的なのは、内部クラスを使用する方法です。 EventHandler
クラスで処理できるのは、内部クラスで処理できるイベントのサブセットに過ぎません。 ただし、長期持続スキームでは、内部クラスよりもEventHandler
のほうが優れています。 また、同じインタフェースを実装している大規模なアプリケーションでEventHandler
を繰返し利用すれば、ディスクやアプリケーションのメモリー・フットプリントを削減できます。
EventHandler
で作成されたリスナーのフットプリントが小さいのは、EventHandler
の依存先のProxy
クラスが同じインタフェースの実装を共有しているからです。 たとえば、EventHandler create
メソッドを使用してアプリケーション内のすべてのActionListener
を作成する場合、すべてのアクション・リスナーは、単一のクラス(Proxy
クラスによって生成されたクラス)のインスタンスになります。 通常、Proxy
クラスのリスナーを使用する場合は、リスナー型 (インタフェース)ごとにリスナー・クラスを1つずつ作成する必要があります。しかし、内部クラスを使用する方法では、リスナー (インタフェースを実装するオブジェクト)ごとにクラスを1つずつ作成するだけで済みます。
通常、EventHandler
のインスタンスを直接扱うことはありません。 その代わりに、EventHandler
のcreate
メソッドを使って、指定されたリスナー・インタフェースを実装するオブジェクトを作成します。 このリスナー・オブジェクトは、内部でEventHandler
オブジェクトを使って、イベントに関する情報、イベント発生時にメッセージを送信されるオブジェクト、送信されるメッセージ(メソッド)、およびメソッドの引数をカプセル化します。 次のセクションでは、例を使って、create
メソッドによるリスナー・オブジェクトの作成方法について説明します。
イベント・ハンドラの使用例
ターゲット・オブジェクト上のメソッドを引数なしで呼び出すリスナーをインストールするというのが、もっとも単純なEventHandler
の利用方法です。 次の例では、javax.swing.JFrame
のインスタンス上のtoFront
メソッドを呼び出すActionListener
を作成します。
myButton.addActionListener( (ActionListener)EventHandler.create(ActionListener.class, frame, "toFront"));
myButton
を押すと、frame.toFront()
文が実行されます。 コンパイル時の型保証を追加しても、同じ結果が得られます。このためには、ActionListener
インタフェースの新しい実装を定義し、そのインスタンスをボタンに追加します。
次に//Equivalent code using an inner class instead of EventHandler. myButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { frame.toFront(); } });
EventHandler
の単純な利用方法として、リスナー・インタフェース(通常はイベント・オブジェクト)内のメソッドの最初の引数からプロパティ値を抽出し、これを使ってターゲット・オブジェクト内のプロパティ値を設定する例を紹介します。 この例では、ターゲット(myButton)オブジェクトのnextFocusableComponent
プロパティをイベントのsourceプロパティの値に設定するActionListener
を作成します。
これは、次の内部クラス実装に対応しています。EventHandler.create(ActionListener.class, myButton, "nextFocusableComponent", "source")
受信イベント・オブジェクトをターゲット・アクションに渡すだけの//Equivalent code using an inner class instead of EventHandler. new ActionListener() { public void actionPerformed(ActionEvent e) { myButton.setNextFocusableComponent((Component)e.getSource()); } }
EventHandler
を作成することもできます。 4番目のEventHandler.create
引数が空の文字列である場合、次のようにしてイベントが渡されます。
これは、次の内部クラス実装に対応しています。EventHandler.create(ActionListener.class, target, "doActionEvent", "")
イベント・オブジェクトのソースからプロパティ値を抽出し、この値をターゲット・オブジェクトのプロパティ値として設定するというのが、おそらくもっとも一般的な//Equivalent code using an inner class instead of EventHandler. new ActionListener() { public void actionPerformed(ActionEvent e) { target.doActionEvent(e); } }
EventHandler
の利用方法でしょう。 次の例では、ターゲット・オブジェクトのlabelプロパティをイベントのソースのtextプロパティの値(sourceプロパティの値)に設定するActionListener
を作成します。
これは、次の内部クラス実装に対応しています。EventHandler.create(ActionListener.class, myButton, "label", "source.text")
イベント・プロパティは、ピリオド(.)で区切られた任意の数のプロパティ接頭辞によって修飾されます。 ピリオドの前に表示される完全指定名は、イベント・オブジェクトに適用されるプロパティ(左から順に適用)の名前として扱われます。//Equivalent code using an inner class instead of EventHandler. new ActionListener { public void actionPerformed(ActionEvent e) { myButton.setLabel(((JTextField)e.getSource()).getText()); } }
たとえば、次のようなアクション・リスナーがあります。
このアクション・リスナーは、次の内部クラスとして書き込まれます(すべてのプロパティが正規の取得メソッドを持ち、適切な型を返すものと想定)。EventHandler.create(ActionListener.class, target, "a", "b.c.d")
ターゲット・プロパティは、ピリオド(.)で区切られた任意の数のプロパティ接頭辞によっても修飾されます。 たとえば、次のようなアクション・リスナーがあります。//Equivalent code using an inner class instead of EventHandler. new ActionListener { public void actionPerformed(ActionEvent e) { target.setA(e.getB().getC().isD()); } }
EventHandler.create(ActionListener.class, target, "a.b", "c.d")このアクション・リスナーは、次の内部クラスとして書き込まれます(すべてのプロパティが正規の取得メソッドを持ち、適切な型を返すものと想定)。
//Equivalent code using an inner class instead of EventHandler. new ActionListener { public void actionPerformed(ActionEvent e) { target.getA().setB(e.getC().isD()); } }
EventHandler
はメソッドを呼び出す際に最終的にリフレクションに依存するため、オーバーロードされたメソッドをターゲットにしないことをお薦めします。 たとえば、ターゲットが次のように定義されたMyTarget
クラスのインスタンスであるとします。
public class MyTarget { public void doIt(String); public void doIt(Object); }これで
doIt
メソッドはオーバーロードされます。 EventHandlerはソースに基づいて適切なメソッドを呼び出します。 ソースがnullの場合は、どちらのメソッドも適しているため、呼び出されるメソッドは不定です。 そのため、オーバーロードされたメソッドをターゲットにしないことをお薦めします。 - 導入されたバージョン:
- 1.4
- 関連項目:
-
コンストラクタのサマリー
コンストラクタコンストラクタ説明EventHandler
(Object target, String action, String eventPropertyName, String listenerMethodName) 新しいEventHandler
オブジェクトを作成します(このコンストラクタを直接呼び出すのではなく、いずれかのcreate
メソッドを使用するのが一般的)。 -
メソッドのサマリー
修飾子と型メソッド説明static <T> T
リスナー・インタフェース内のすべてのメソッドがハンドラのaction
をtarget
に適用するようなlistenerInterface
実装を作成します。static <T> T
/** すべてのメソッドが、イベント式eventPropertyName
の値を文中のfinalメソッドであるaction
(target
に適用される)に渡すようなlistenerInterface
実装を作成します。static <T> T
create
(Class<T> listenerInterface, Object target, String action, String eventPropertyName, String listenerMethodName) listenerMethodName
という名前のメソッドが、イベント式eventPropertyName
の値を文中のfinalメソッドであるaction
(target
に適用される)に渡すようなlistenerInterface
実装を作成します。このイベント・ハンドラによって設定されるターゲットの書込み可能なプロパティ、またはこのイベントがターゲット上で呼び出すメソッドの名前を返します。ターゲットに適用されるアクションで使用されるイベントのプロパティを返します。アクションをトリガーするメソッドの名前を返します。このイベント・ハンドラがメッセージの送信先とするオブジェクトを返します。イベントから適切なプロパティ値を抽出し、このEventHandler
に関連付けられているアクションに渡します。
-
コンストラクタの詳細
-
EventHandler
@ConstructorProperties({"target","action","eventPropertyName","listenerMethodName"}) public EventHandler(Object target, String action, String eventPropertyName, String listenerMethodName) 新しいEventHandler
オブジェクトを作成します(このコンストラクタを直接呼び出すのではなく、いずれかのcreate
メソッドを使用するのが一般的)。eventPropertyName
およびlistenerMethodName
パラメータの詳細は、the general version of create
を参照してください。- パラメータ:
target
- アクションを実行するオブジェクトaction
- ターゲット上の(修飾されている可能性がある)プロパティまたはメソッドの名前eventPropertyName
- 受信イベントの読取り可能なプロパティの(修飾されている可能性がある)名前listenerMethodName
- アクションをトリガーするべきリスナー・インタフェース内のメソッドの名前- 例外:
NullPointerException
-target
がnullである場合NullPointerException
-action
がnullである場合- 関連項目:
-
-
メソッドの詳細
-
getTarget
public Object getTarget()このイベント・ハンドラがメッセージの送信先とするオブジェクトを返します。- 戻り値:
- このイベント・ハンドラのターゲット
- 関連項目:
-
getAction
public String getAction()このイベント・ハンドラによって設定されるターゲットの書込み可能なプロパティ、またはこのイベントがターゲット上で呼び出すメソッドの名前を返します。- 戻り値:
- このイベント・ハンドラのアクション
- 関連項目:
-
getEventPropertyName
public String getEventPropertyName()ターゲットに適用されるアクションで使用されるイベントのプロパティを返します。- 戻り値:
- イベントのプロパティ
- 関連項目:
-
getListenerMethodName
public String getListenerMethodName()アクションをトリガーするメソッドの名前を返します。 戻り値null
は、リスナー・インタフェース内のすべてのメソッドがアクションをトリガーすることを表します。- 戻り値:
- アクションをトリガーするメソッドの名前
- 関連項目:
-
invoke
イベントから適切なプロパティ値を抽出し、このEventHandler
に関連付けられているアクションに渡します。- 定義:
invoke
、インタフェースInvocationHandler
- パラメータ:
proxy
- プロキシ・オブジェクトmethod
- リスナー・インタフェース内のメソッドarguments
- プロキシ・インスタンスでのメソッド呼出し時に渡される引数値を格納するオブジェクト配列。インタフェース・メソッドが引数を取らない場合、null
となる。 プリミティブ型の引数は、java.lang.Integer
やjava.lang.Boolean
などの適切なプリミティブ・ラッパー・クラスのインスタンスにラップされる。- 戻り値:
- ターゲットにアクションを適用した結果
- 関連項目:
-
create
リスナー・インタフェース内のすべてのメソッドがハンドラのaction
をtarget
に適用するようなlistenerInterface
実装を作成します。 このメソッドは、null
値をとるeventPropertyName
とlistenerMethodName
の両方を持つ、ほかのより一般的な実装のcreate
メソッドを呼び出すことによって実装されます。action
パラメータの詳細は、the general version of create
を参照してください。次に、
dialog.show()
を使って、JDialog
を表示するActionListener
を作成する例を示します。EventHandler.create(ActionListener.class, dialog, "show")
- 型パラメータ:
T
- 作成する型- パラメータ:
listenerInterface
- プロキシの作成対象となるリスナー・インタフェースtarget
- アクションを実行するオブジェクトaction
- ターゲット上の(修飾されている可能性がある)プロパティまたはメソッドの名前- 戻り値:
listenerInterface
を実装するオブジェクト- 例外:
NullPointerException
-listenerInterface
がnullである場合NullPointerException
-target
がnullである場合NullPointerException
-action
がnullである場合IllegalArgumentException
-listenerInterface
のプロキシを作成するとProxy.newProxyInstance(java.lang.ClassLoader, java.lang.Class<?>[], java.lang.reflect.InvocationHandler)
で指定された制限のいずれかが失敗した場合- 関連項目:
-
create
public static <T> T create(Class<T> listenerInterface, Object target, String action, String eventPropertyName) /** すべてのメソッドが、イベント式eventPropertyName
の値を文中のfinalメソッドであるaction
(target
に適用される)に渡すようなlistenerInterface
実装を作成します。 このメソッドは、null
値をとるlistenerMethodName
を持つ、より一般的な実装のcreate
メソッドを呼び出すことによって実装されます。action
およびeventPropertyName
パラメータの詳細は、the general version of create
を参照してください。次のコードを使って、
JLabel
のテキストを受信イベントのJTextField
ソースのテキスト値に設定するActionListener
を作成できます。EventHandler.create(ActionListener.class, label, "text", "source.text");
//Equivalent code using an inner class instead of EventHandler. new ActionListener() { public void actionPerformed(ActionEvent event) { label.setText(((JTextField)(event.getSource())).getText()); } };
- 型パラメータ:
T
- 作成する型- パラメータ:
listenerInterface
- プロキシの作成対象となるリスナー・インタフェースtarget
- アクションを実行するオブジェクトaction
- ターゲット上の(修飾されている可能性がある)プロパティまたはメソッドの名前eventPropertyName
- 受信イベントの読取り可能なプロパティの(修飾されている可能性がある)名前- 戻り値:
listenerInterface
を実装するオブジェクト- 例外:
NullPointerException
-listenerInterface
がnullである場合NullPointerException
-target
がnullである場合NullPointerException
-action
がnullである場合IllegalArgumentException
-listenerInterface
のプロキシを作成するとProxy.newProxyInstance(java.lang.ClassLoader, java.lang.Class<?>[], java.lang.reflect.InvocationHandler)
で指定された制限のいずれかが失敗した場合- 関連項目:
-
create
public static <T> T create(Class<T> listenerInterface, Object target, String action, String eventPropertyName, String listenerMethodName) listenerMethodName
という名前のメソッドが、イベント式eventPropertyName
の値を文中のfinalメソッドであるaction
(target
に適用される)に渡すようなlistenerInterface
実装を作成します。 その他のリスナー・メソッドは、何も処理を行いません。eventPropertyName
文字列は、ターゲット・メソッドに渡される受信イベント・オブジェクトから値を抽出するために使用されます。 一般に、ターゲット・メソッドは引数を取らないため、eventPropertyName
でnull値を使用するようにしてください。 また、受信イベント・オブジェクトをターゲット・メソッドに直接渡すには、空の文字列を使用します。eventPropertyName
文字列の形式は、メソッドまたはプロパティのシーケンスで、それぞれのメソッドまたはプロパティは、着信するイベント・オブジェクトから始まる直前のメソッドによって返される値に適用されます。 構文は次のとおりです。propertyName{.propertyName}*
ここでpropertyName
はメソッドまたはプロパティに一致します。 たとえばpoint
プロパティをMouseEvent
から抽出するには、"point"
または"getPoint"
をeventPropertyName
として使用できます。 textプロパティをJLabel
ソースを持つMouseEvent
から抽出するには、"source.text"
、"getSource.text"、"getSource.getText"
または"source.getText"
をeventPropertyName
として使用します。 メソッドが見つからない場合、またはメソッドの呼出しで例外が生成された場合は、ディスパッチ時にRuntimeException
がスローされます。 たとえば受信イベント・オブジェクトがnullで、eventPropertyName
がnullでも空でもない場合は、RuntimeException
がスローされます。action
引数の形式はeventPropertyName
引数の形式と同じで、最後のプロパティ名はメソッド名または書込み可能なプロパティを表します。listenerMethodName
がnull
の場合は、インタフェース内のすべてのメソッドが、target
上で実行されるaction
をトリガーします。たとえば、マウス・ボタンを押すたびにターゲット・オブジェクトの
origin
プロパティを受信するMouseEvent
の場所(mouseEvent.getPoint()
の値)に設定するMouseListener
を作成したい場合は、次のように記述します。EventHandler.create(MouseListener.class, target, "origin", "point", "mousePressed");
mousePressed
を除くすべてのメソッドが操作不能であるMouseListener
の記述と同じです。//Equivalent code using an inner class instead of EventHandler. new MouseAdapter() { public void mousePressed(MouseEvent e) { target.setOrigin(e.getPoint()); } };
- 型パラメータ:
T
- 作成する型- パラメータ:
listenerInterface
- プロキシの作成対象となるリスナー・インタフェースtarget
- アクションを実行するオブジェクトaction
- ターゲット上の(修飾されている可能性がある)プロパティまたはメソッドの名前eventPropertyName
- 受信イベントの読取り可能なプロパティの(修飾されている可能性がある)名前listenerMethodName
- アクションをトリガーするべきリスナー・インタフェース内のメソッドの名前- 戻り値:
listenerInterface
を実装するオブジェクト- 例外:
NullPointerException
-listenerInterface
がnullである場合NullPointerException
-target
がnullである場合NullPointerException
-action
がnullである場合IllegalArgumentException
-listenerInterface
のプロキシを作成するとProxy.newProxyInstance(java.lang.ClassLoader, java.lang.Class<?>[], java.lang.reflect.InvocationHandler)
で指定された制限のいずれかが失敗した場合- 関連項目:
-