16.5. DRL でのタイプ宣言とメタデータ
DRL ファイルの宣言は、DRL ファイルのルールで使用するファクトタイプまたはメタデータを新たに定義します。
-
新規ファクトタイプ: Red Hat Decision Manager に含まれる
java.lang
パッケージのデフォルトのファクトタイプはObject
ですが、必要に応じて DRL ファイルで他のタイプを宣言できます。DRL ファイルにファクトタイプを宣言すると、Java などの低級言語でモデルを作成せず、デシジョンエンジンに直接新しいファクトモデルを定義するようになります。また、ドメインモデルがすでにビルドされていて、推論 (reasoning) のプロセスで主に使用する追加のエンティティーでこのモデルを補完する場合に、新規タイプを宣言することもできます。 -
ファクトタイプのメタデータ:
@key(value)
形式のメタデータを新規または既存のファクトを関連付けることができます。メタデータには、ファクト属性で表現されていない、該当のファクトタイプのすべてのインスタンス間で一貫性のあるすべての種類のデータを使用できます。メタデータはランタイム時に、デシジョンエンジンでクエリーでき、推論 (reasoning) のプロセスで使用できます。
16.5.1. DRL のメタデータを使用しないタイプ宣言
新規ファクトの宣言にメタデータは必要ありませんが、属性またはフィールドのリストを含める必要があります。タイプ宣言に指定属性が含まれていない場合は、デシジョンエンジンがクラスパス内で既存のファクトクラスを検索し、クラスが見つからない場合はエラーを出します。
以下の例は、DRL ファイルにメタデータがない新規ファクトタイプ Person
の宣言です。
ルールが 1 つ含まれる新規ファクトタイプの宣言の例
declare Person name : String dateOfBirth : java.util.Date address : Address end rule "Using a declared type" when $p : Person( name == "James" ) then // Insert Mark, who is a customer of James. Person mark = new Person(); mark.setName( "Mark" ); insert( mark ); end
この例では、新規ファクトタイプ Person
には name
、dateOfBirth
、および address
の 3 つの属性が含まれます。属性ごとにタイプがあり、このタイプには作成する別のクラスや以前に宣言したファクトタイプなどの、有効な Java タイプを指定できます。dateOfBirth
属性には、Java API からの java.util.Date
タイプがあり、address
属性には、以前に定義したファクトタイプ Address
が含まれます。
宣言するたびにクラスの完全修飾名が記述されないように、完全なクラス名を import
句の一部として定義できます。
インポートの完全修飾クラス名でのタイプ宣言例
import java.util.Date declare Person name : String dateOfBirth : Date address : Address end
新規のファクトタイプを宣言すると、デシジョンエンジンはコンパイル時にファクトタイプを表す Java クラスを生成します。生成される Java クラスはタイプ定義の一対一の JavaBeans マッピングとなります。
たとえば、以下の Java クラスは Person
タイプ宣言例から生成されます。
Person ファクトタイプの宣言用に生成された Java クラス
public class Person implements Serializable { private String name; private java.util.Date dateOfBirth; private Address address; // Empty constructor public Person() {...} // Constructor with all fields public Person( String name, Date dateOfBirth, Address address ) {...} // If keys are defined, constructor with keys public Person( ...keys... ) {...} // Getters and setters // `equals` and `hashCode` // `toString` }
Person
タイプ宣言が含まれる以前のルールの例が示すように、他のファクトと同様にルールで生成したクラスを使用できます。
宣言された Person ファクトタイプを使用するルールの例
rule "Using a declared type" when $p : Person( name == "James" ) then // Insert Mark, who is a customer of James. Person mark = new Person(); mark.setName( "Mark" ); insert( mark ); end
16.5.2. DRL の列挙タイプの宣言
DRL は、declare enum <factType>
形式の列挙タイプの宣言をサポートします。列挙タイプの後にはコンマ区切りの値のリストが続き、最後はセミコロンで終了します。これにより、DRL ファイルのルールで列挙リストを使用できます。
たとえば、以下の列挙タイプの宣言では、従業員スケジュールルールの曜日を定義します。
スケジュールルールを使用した列挙タイプ宣言の例
declare enum DaysOfWeek SUN("Sunday"),MON("Monday"),TUE("Tuesday"),WED("Wednesday"),THU("Thursday"),FRI("Friday"),SAT("Saturday"); fullName : String end rule "Using a declared Enum" when $emp : Employee( dayOff == DaysOfWeek.MONDAY ) then ... end
16.5.3. DRL の拡張タイプ宣言
DRL は、declare <factType1> extends <factType2>
形式のタイプ宣言の継承をサポートします。DRL で宣言したサブタイプで Java で宣言したタイプを拡張するには、フィールドなしの宣言ステートメントで親タイプを繰り返し使用します。
たとえば、以下のタイプ宣言はトップレベルの Person
タイプから Student
タイプを拡張し、さらに Student
サブタイプから LongTermStudent
タイプを拡張します。
拡張タイプ宣言の例
import org.people.Person declare Person end declare Student extends Person school : String end declare LongTermStudent extends Student years : int course : String end
16.5.4. DRL のメタデータが含まれるタイプ宣言
@key(value)
(値は任意) 形式のメタデータをファクトタイプまたはファクト属性に関連付けることができます。メタデータには、ファクト属性で表現されていない、該当のファクトタイプのすべてのインスタンス間で一貫性のあるすべての種類のデータを使用できます。メタデータはランタイム時に、デシジョンエンジンでクエリーでき、推論 (reasoning) のプロセスで使用できます。ファクトタイプの属性の前に宣言するメタデータはファクトタイプに割り当てられ、属性の後に宣言するメタデータはこの特定の属性に割り当てられます。
以下の例では、@author
と @dateOfCreation
のメタデータ属性 2 つが Person
ファクトタイプに、@key
と @maxLength
のメタデータアイテム 2 つが name
属性に割り当てられています。@key
メタデータ属性には必須の値がないので、括弧と値は省略されます。
ファクトタイプおよび属性のメタデータ宣言例
import java.util.Date declare Person @author( Bob ) @dateOfCreation( 01-Feb-2009 ) name : String @key @maxLength( 30 ) dateOfBirth : Date address : Address end
既存タイプのメタデータ属性を宣言する場合には、すべての宣言の import
句の一部として、または個別の declare
句の一部として完全修飾クラス名を特定できます。
インポートタイプのメタデータ宣言の例
import org.drools.examples.Person declare Person @author( Bob ) @dateOfCreation( 01-Feb-2009 ) end
宣言タイプのメタデータ宣言例
declare org.drools.examples.Person @author( Bob ) @dateOfCreation( 01-Feb-2009 ) end
16.5.5. DRL でのファクトタイプと属性宣言のメタデータタグ
DRL 宣言でカスタムメタデータ属性を定義できますが、デシジョンエンジンはファクトタイプまたはファクトタイプ属性の宣言に対する次の定義済みメタデータタグもサポートします。
VoiceCall
クラスを参照するこのセクションの例では、サンプルアプリケーションドメインモデルに以下のクラスの詳細が含まれていることを前提としています。
Telecom ドメインモデルの例における VoiceCall ファクトクラス
public class VoiceCall { private String originNumber; private String destinationNumber; private Date callDateTime; private long callDuration; // in milliseconds // Constructors, getters, and setters }
- @role
このタグは、指定のファクトタイプが複雑なイベントの処理時にデシジョンエンジンにて通常のファクトまたはイベントとして処理されるかどうかを決定します。
デフォルトパラメーター:
fact
サポート対象のパラメーター:
fact
、event
@role( fact | event )
例: イベントタイプとして VoiceCall の宣言
declare VoiceCall @role( event ) end
- @timestamp
このタグは、デシジョンエンジンのすべてのイベントに自動的に割り当てられます。デフォルトでは、この時間はセッションクロックにより提供され、デシジョンエンジンのワーキングメモリーへの挿入時にイベントに割り当てられます。セッションクロックが追加するデフォルトのタイムスタンプの代わりに、カスタムのタイムスタンプ属性を指定できます。
デフォルトパラメーター: デシジョンエンジンのセッションクロックが追加する時間
サポート対象のパラメーター: セッションクロックタイムまたはカスタムのタイムスタンプ属性
@timestamp( <attributeName> )
例: VoiceCall のタイムスタンプ属性の宣言
declare VoiceCall @role( event ) @timestamp( callDateTime ) end
- @duration
このタグは、デシジョンエンジンのイベントの持続期間を決定します。イベントは、interval-based イベントまたは point-in-time イベントのいずれかになります。interval-based のイベントには持続期間があり、その持続期間が経過するまでデシジョンエンジンのワーキングメモリーで持続します。point-in-time イベントに持続期間はなく、基本的には期間がゼロの interval-based イベントになります。デフォルトでは、デシジョンエンジンのすべてのイベントの持続期間は 0 です。デフォルトの代わりに、カスタムの持続期間属性を指定できます。
デフォルトパラメーター: Null (ゼロ)
サポート対象のパラメーター: カスタムの持続期間属性
@duration( <attributeName> )
例: VoiceCall の持続期間属性の宣言
declare VoiceCall @role( event ) @timestamp( callDateTime ) @duration( callDuration ) end
- @expires
このタグは、デシジョンエンジンのワーキングメモリーでイベントの有効期限が切れるまでの時間を決定します。デフォルトでは、イベントは現在のルールのいずれにも一致せず、それらのいずれもアクティベートできなくなった時点で失効します。イベント失効までの期間を定義できます。また、このタグの定義は、KIE ベースの一時的な制約やスライディングウィンドウから算出した暗黙的な有効期限のオフセットもオーバーライドします。デシジョンエンジンがストリームモードで実行中の場合にのみ、このタグを使用できます。
デフォルトパラメーター: Null (イベントがルールに一致せず、ルールをアクティブにできなくなるとイベントの有効期限が切れる)
サポート対象のパラメーター:
[#d][#h][#m][#s][[ms]]
形式のカスタムのtimeOffset
属性@expires( <timeOffset> )
例: VoiceCall イベントに対する有効期限のオフセットの宣言
declare VoiceCall @role( event ) @timestamp( callDateTime ) @duration( callDuration ) @expires( 1h35m ) end
- @typesafe
このタグは、型安全性を有効して/有効にせずに指定のファクトタイプをコンパイルするかどうかを決定します。デフォルトでは、すべてのタイプ宣言は型安全性が有効な状態でコンパイルされます。この動作を type-unsafe の評価にオーバーライドすることもできます。type-unsafe の評価の場合、すべての制約は MVEL 制約として生成され、動的に実行されます。これは、一般的なコレクションではない場合や、タイプが混同されているコレクションを処理する場合に便利です。
デフォルトパラメーター:
true
サポート対象のパラメーター:
true
、false
@typesafe( <boolean> )
例: type-unsafe 評価の VoiceCall の宣言
declare VoiceCall @role( fact ) @typesafe( false ) end
- @serialVersionUID
このタグは、ファクト宣言でシリアル化可能なクラスの
serialVersionUID
の指定値を定義します。シリアル化可能なクラスで明示的にserialVersionUID
が宣言されていない場合は、Java Object Serialization Specification に記載されているように、シリアル化のランタイムが、そのクラスのさまざまな側面に基づいてそのクラスのデフォルトのserialVersionUID
値を計算します。ただし、デシリアル化の結果を最適化し、シリアル化した KIE セッションの互換性を向上するには、関連のクラスや DRL 宣言の要件に応じてserialVersionUID
を設定します。デフォルトパラメーター: Null
サポート対象のパラメーター: カスタムの
serialVersionUID
整数@serialVersionUID( <integer> )
例: VoiceCall クラスの serialVersionUID の宣言
declare VoiceCall @serialVersionUID( 42 ) end
- @key
このタグを指定すると、ファクトタイプ属性をファクトタイプのキー識別子として使用できるようになります。生成されたクラスは
equals()
メソッドとhashCode()
メソッドを実装できるようになり、該当タイプの 2 つのインスタンスが同等であるかを判別できるようになります。デシジョンエンジンは、すべてのキー属性をパラメーターとして使用してコンストラクターを生成することもできます。デフォルトパラメーター: なし
サポート対象のパラメーター: なし
<attributeDefinition> @key
例: Person タイプ属性をキーとして宣言する
declare Person firstName : String @key lastName : String @key age : int end
この例では、デシジョンエンジンは
firstName
属性とlastName
属性をチェックして、Person
の 2 つのインスタンスが同等であるかどうかを判断しますが、age
属性はチェックしません。また、このデシジョンエンジンは暗黙的に 3 つのコンストラクターを生成します。1 つはパラメーターなし、もう 1 つ目は@key
フィールドのあるコンストラクター、3 つ目はすべてのフィールドのあるコンストラクターです。キー宣言に基づくコンストラクターの例
Person() // Empty constructor Person( String firstName, String lastName ) Person( String firstName, String lastName, int age )
以下の例のように、キーコンストラクターに基づいてタイプのインスタンスを作成できます。
キーコンストラクターを使用したインスタンスの例
Person person = new Person( "John", "Doe" );
- @position
このタグは、位置引数で宣言されたファクトタイプ属性またはフィールドの位置を決定し、デフォルトで宣言した属性の順番をオーバーライドします。このタグを使用して、タイプ宣言または位置引数で制約の形式を維持しつつ、パターンの位置制約を変更できます。このタグは、クラスパスのクラスにあるフィールドに対してのみ使用できます。1 つのクラスのフィールドでこのタグを使用する場合も、使用しない場合もありますが、このタグのない属性は、宣言の順番では最後になります。クラスの継承はサポートされますが、メソッドのインターフェイスはサポートされません。
デフォルトパラメーター: なし
サポート対象のパラメーター: 整数
<attributeDefinition> @position ( <integer> )
例: ファクトタイプを宣言し、宣言した順番をオーバライドする
declare Person firstName : String @position( 1 ) lastName : String @position( 0 ) age : int @position( 2 ) occupation: String end
この例では、位置引数に含まれる属性の優先順位は以下のとおりです。
-
lastName
-
firstName
-
age
-
occupation
位置引数では、位置が既知の名前付きフィールドにマッピングされるため、フィールド名を指定する必要はありません。たとえば、
Person( lastName == "Doe" )
の引数はPerson( "Doe"; )
と同じです。ここでは、lastName
フィールドには、DRL 宣言の最上位の位置アノテーションが含まれます。セミコロン;
は、その前にあるものはすべて位置引数であることを示します。セミコロンを使用して引数を区切ることで、パターンで位置引数と名前付き引数を混ぜて使用できます。バインドされていない位置引数の変数は、その位置にマッピングされているフィールドにバインドされます。以下のパターン例では、位置引数と名前付き引数をさまざまな方法で構築する方法を示します。このパターンには、制約が 2 つ、バインディングが 1 つ含まれており、セミコロンで位置引数のセクションと名前付き引数のセクションを分けています。位置引数では、変数とリテラル、およびリテラルのみを使用する式がサポートされていますが、変数だけの使用はサポートされていません。
位置引数および名前付き引数を含むパターン例
Person( "Doe", "John", $a; ) Person( "Doe", "John"; $a : age ) Person( "Doe"; firstName == "John", $a : age ) Person( lastName == "Doe"; firstName == "John", $a : age )
位置引数は、入力引数 または 出力引数 とに分類できます。入力引数は、以前に宣言したバインディングと、ユニフィケーション (unification) を使用したそのバインディングに対する制約が含まれます。出力引数は、この宣言を生成して、バインディングがまだ存在しない場合は、これを位置引数で表現するフィールドにバインディングします。
拡張タイプの宣言で
@position
アノテーションを定義する場合は、属性の位置がサブタイプに継承されるため注意が必要です。このように継承されることで、属性の順番が混同し、混乱を生じさせる可能性があります。2 つのフィールドに同じ@position
の値を指定でき、連続する値は宣言する必要がありません。位置が繰り返し使用される場合は、継承を使用することで競合が発生しないように解決されます。この場合は、親タイプの位置の値の優先順位が高く、その後は最初から最後の順番で宣言を使用します。たとえば、以下の拡張タイプ宣言では、位置の優先順位が混合します。
位置アノテーションが混合した拡張ファクトタイプの例
declare Person firstName : String @position( 1 ) lastName : String @position( 0 ) age : int @position( 2 ) occupation: String end declare Student extends Person degree : String @position( 1 ) school : String @position( 0 ) graduationDate : Date end
この例では、位置引数に含まれる属性の優先順位は以下のとおりです。
-
lastName
(親タイプでの位置 0) -
school
(サブタイプでの位置 0) -
firstName
(親タイプでの位置 1) -
degree
(サブタイプでの位置 1) -
age
(親タイプでの位置 2 ) -
occupation
(位置アノテーションがない最初のフィールド) -
graduationDate
(位置アノテーションがない 2 番目のフィールド)
-
16.5.6. ファクトタイプに対するプロパティー変更の設定およびリスナー
デフォルトでは、デシジョンエンジンは、ルールがトリガーされるたびに、ファクトタイプに対するすべてのファクトパターンを再評価しません。代わりに、指定のパターン内に制約またはバインドされている変更されたプロパティーのみに対応します。たとえば、ルールが、ルールアクションの一環として modify()
を呼び出すものの、アクションが KIE ベースで新しいデータを生成しない場合は、データが変更されないため、デシジョンエンジンはすべてのファクトパターンを自動的に再評価しません。このプロパティーのリアクティビティー動作は、KIE ベースでの不要な再帰を阻止し、より効率的なルール評価をもたらします。また、この動作は無限再帰を回避するために no-loop
ルール属性を必ずしも使用する必要がないことを意味します。
以下の KnowledgeBuilderConfiguration
オプションを使用して、このプロパティーリアクティビティー動作を変更または無効にできます。次に、Java クラスまたは DRL ファイルでプロパティー変更設定を使用し、必要に応じてプロパティーリアクティビティーを調整します。
-
ALWAYS
: (デフォルト) すべてのタイプはプロパティーリアクティブです。ただし、@classReactive
プロパティー変更設定を使用して、特定タイプのプロパティーリアクティビティーを無効にできます。 -
ALLOWED
: すべてのタイプはプロパティーリアクティブではありません。ただし、@propertyReactive
プロパティー変更設定を使用して、特定タイプのプロパティーリアクティビティーを有効にできます。 -
DISABLED
: すべてのタイプはプロパティーリアクティブではありません。すべてのプロパティー変更リスナーは無視されます。
KnowledgeBuilderConfiguration におけるプロパティーリアクティビティー設定の例
KnowledgeBuilderConfiguration config = KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration(); config.setOption(PropertySpecificOption.ALLOWED); KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(config);
または、Red Hat Decision Manager ディストリビューションにおける standalone.xml
ファイルの drools.propertySpecific
システムプロパティーを更新できます。
システムプロパティーにおけるプロパティーリアクティビティー設定の例
<system-properties> ... <property name="drools.propertySpecific" value="ALLOWED"/> ... </system-properties>
デシジョンエンジンは、ファクトクラスまたは宣言された DRL ファクトタイプに対して、以下のプロパティー変更の設定およびリスナーをサポートします。
- @classReactive
デシジョンエンジンでプロパティーリアクティビティーが
ALWAYS
に設定されている場合 (すべてのタイプはプロパティーリアクティブ)、このタグは特定の Java クラスまたは宣言された DRL ファクトタイプに対してデフォルトのプロパティーリアクティビティー動作を無効にします。このタグは、特定パターン内に制約またはバインドされる変更されたプロパティーのみに対応するのではなく、ルールがトリガーされるたびに指定されたファクトタイプのすべてのファクトパターンをデシジョンエンジンが再評価する必要がある場合に使用できます。例: DRL タイプの宣言におけるデフォルトのプロパティーリアクティビティーの無効化
declare Person @classReactive firstName : String lastName : String end
例: Java クラスにおけるデフォルトのプロパティーリアクティビティーの無効化
@classReactive public static class Person { private String firstName; private String lastName; }
- @propertyReactive
プロパティーリアクティビティーがデシジョンエンジンで
ALLOWED
に設定されている場合 (指定されていない場合、すべてのタイプはプロパティーリアクティブではない)、このタグは特定の Java クラスまたは宣言された DRL ファクトタイプに対してプロパティーリアクティビティーを有効にします。ルールがトリガーされるたびにファクトのすべてのファクトパターンを再評価するのではなく、指定されたファクトタイプの特定のパターン内で制約またはバインドされた変更済みプロパティーにのみデシジョンエンジンを反応させる場合は、このタグを使用できます。例: DRL タイプの宣言におけるプロパティーリアクティビティーの有効化 (リアクティビティーがグローバルに無効にされる場合)
declare Person @propertyReactive firstName : String lastName : String end
例: Java クラスでのプロパティーのリアクティビティーの有効化 (リアクティビティーがグローバルに無効にされる場合)
@propertyReactive public static class Person { private String firstName; private String lastName; }
- @watch
このタグは、DRL ルールのファクトパターンで、インラインで指定する追加のプロパティーに対するプロパティーリアクティビティーを有効にします。このタグがサポートされるのは、デシジョンエンジンでプロパティーリアクティビティーが
ALWAYS
に設定されている場合か、プロパティーリアクティビティーがALLOWED
に設定され、関連するファクトタイプが@propertyReactive
タグを使用する場合に限られます。DRL ルールでこのタグを使用して、ファクトプロパティーリアクティビティー論理の指定されたプロパティーを追加または除外できます。デフォルトパラメーター: なし
サポートされているパラメーター: プロパティー名、
*
(all)、!
(not)、!*
(no properties)<factPattern> @watch ( <property> )
例: ファクトパターンにおけるプロパティーリアクティビティーの有効化または無効化
// Listens for changes in both `firstName` (inferred) and `lastName`: Person(firstName == $expectedFirstName) @watch( lastName ) // Listens for changes in all properties of the `Person` fact: Person(firstName == $expectedFirstName) @watch( * ) // Listens for changes in `lastName` and explicitly excludes changes in `firstName`: Person(firstName == $expectedFirstName) @watch( lastName, !firstName ) // Listens for changes in all properties of the `Person` fact except `age`: Person(firstName == $expectedFirstName) @watch( *, !age ) // Excludes changes in all properties of the `Person` fact (equivalent to using `@classReactivity` tag): Person(firstName == $expectedFirstName) @watch( !* )
デシジョンエンジンは、
@classReactive
タグ (プロパティーリアクティビティーを無効にする) を使用するファクトタイプのプロパティーに対して@watch
タグを使用する場合、またはデシジョンエンジンでプロパティーリアクティビティーがALLOWED
に設定され、関連するファクトタイプが@propertyReactive
タグを使用しない場合は、コンパイルエラーを生成します。また、@watch( firstName, ! firstName )
などのリスナーアノテーションでプロパティーを複製する場合でも、コンパイルエラーが生じます。- @propertyChangeSupport
JavaBeans Specification で定義されたプロパティー変更のサポートを実装するファクトの場合は、このタグによりデシジョンエンジンがファクトプロパティーの変更を監視できるようになります。
例: JavaBeans オブジェクトでのプロパティー変更のサポートの宣言
declare Person @propertyChangeSupport end
16.5.7. アプリケーションコード内の DRL で宣言されたタイプへのアクセス
DRL の宣言タイプは通常 DRL ファイル内で使用され、Java モデルは通常モデルをルールとアプリケーション間で共有する場合に使用されます。宣言タイプは KIE ベースのコンパイル時に生成されるため、アプリケーションはアプリケーションのランタイムまでこの宣言タイプにアクセスできません。状況によっては、アプリケーションが宣言タイプからファクトに直接アクセスし、処理する必要があります (とくにアプリケーションがデシジョンエンジンをラップして、ルール管理用によりレベルの高い、ドメイン固有のユーザーインターフェイスを提供する場合)。
アプリケーションコードから宣言タイプを直接処理するには、Red Hat Decision Manager で org.drools.definition.type.FactType
API を使用します。この API を使用して、宣言ファクトタイプでフィールドのインスタンス化、読み取り、書き込みを行います。
以下のコード例では、アプリケーションから Person
ファクトタイプを直接変更します。
FactType API を使用した宣言されたファクトタイプを処理するアプリケーションコード例
import java.util.Date; import org.kie.api.definition.type.FactType; import org.kie.api.KieBase; import org.kie.api.runtime.KieSession; ... // Get a reference to a KIE base with the declared type: KieBase kbase = ... // Get the declared fact type: FactType personType = kbase.getFactType("org.drools.examples", "Person"); // Create instances: Object bob = personType.newInstance(); // Set attribute values: personType.set(bob, "name", "Bob" ); personType.set(bob, "dateOfBirth", new Date()); personType.set(bob, "address", new Address("King's Road","London","404")); // Insert the fact into a KIE session: KieSession ksession = ... ksession.insert(bob); ksession.fireAllRules(); // Read attributes: String name = (String) personType.get(bob, "name"); Date date = (Date) personType.get(bob, "dateOfBirth");
API には、一度にすべての属性を設定したり、Map
コレクションから値を読み取ったり、すべての属性を一度に Map
コレクションに読み込んだりするなど、他の便利なメソッドも含まれます。
API の動作は Java リフレクションと似ていますが、API はリフレクションを使用せず、生成されたバイトコードで実装され性能が良いアクセサーに依存します。