- メソッドやフィールドのメソッド・ハンドルの作成に役立つルックアップ・メソッド。
- 既存のメソッド・ハンドルを組み合わせたり変換したりして新しいハンドルを作成するコンビネータ・メソッド。
- その他の一般的なJVM操作や制御フロー・パターンをエミュレートするメソッド・ハンドルを作成する、その他のファクトリ・メソッド。
IllegalArgumentException
がスローされます。- 導入されたバージョン:
- 1.7
-
ネストされたクラスのサマリー
ネストされたクラス修飾子と型クラス説明static final class
ルックアップ・オブジェクトは、メソッド・ハンドルの作成にアクセス・チェックが必要な場合のメソッド・ハンドル作成用ファクトリです。 -
メソッドのサマリー
修飾子と型メソッド説明static MethodHandle
arrayConstructor
(Class<?> arrayClass) anewarray
バイトコードの場合と同様に、必要な型の配列を構築するメソッド・ハンドルを生成します。static MethodHandle
arrayElementGetter
(Class<?> arrayClass) aaload
バイトコードの場合と同様に、配列の要素に対する読み取りアクセスを提供するメソッド・ハンドルを生成します。static MethodHandle
arrayElementSetter
(Class<?> arrayClass) astore
バイトコードの場合と同様に、配列の要素への書き込みアクセスを与えるメソッド・ハンドルを生成します。static VarHandle
arrayElementVarHandle
(Class<?> arrayClass) 型arrayClass
の配列の要素にアクセスするVarHandleを生成します。static MethodHandle
arrayLength
(Class<?> arrayClass) arraylength
バイトコードの場合と同様に、配列の長さを返すメソッド・ハンドルを生成します。static VarHandle
byteArrayViewVarHandle
(Class<?> viewArrayClass, ByteOrder byteOrder) int[]
やlong[]
など、異なるプリミティブ配列型であるかのように見えるbyte[]
配列の要素へのアクセス権を付与するVarHandleを生成します。static VarHandle
byteBufferViewVarHandle
(Class<?> viewArrayClass, ByteOrder byteOrder) int[]
またはlong[]
など、byte
の要素にアクセスするVarHandleを生成します。これは、ByteBuffer
の要素と異なるプリミティブ・コンポーネント型の要素の配列であるかのように見えます。static MethodHandle
catchException
(MethodHandle target, Class<? extends Throwable> exType, MethodHandle handler) ターゲットのメソッド・ハンドルを例外ハンドラの内部で実行することによって、このターゲットを適応させるメソッド・ハンドルを作成します。static <T> T
classData
(MethodHandles.Lookup caller, String name, Class<T> type) 指定されたcaller
ルックアップ・オブジェクトまたはnull
のルックアップ・クラスに関連付けられた「クラス・データ」を返します。static <T> T
classDataAt
(MethodHandles.Lookup caller, String name, Class<T> type, int index) 指定されたcaller
ルックアップ・オブジェクトのルックアップ・クラスに関連付けられているクラス・データがList
の場合、「クラス・データ」の指定された索引にある要素を返します。static MethodHandle
collectArguments
(MethodHandle target, int pos, MethodHandle filter) ターゲット・メソッド・ハンドルを、フィルタ(別のメソッド・ハンドル)でその引数のサブシーケンスを前処理することにより、適応させます。static VarHandle
collectCoordinates
(VarHandle target, int pos, MethodHandle filter) フィルタ(メソッド・ハンドル)を使用して座標値のサブ・シーケンスを前処理することで、ターゲット変数ハンドルを調整します。static MethodHandle
要求された戻り値の型を持ち、呼び出されるたびに指定された定数値を返すメソッド・ハンドルを生成します。static MethodHandle
countedLoop
(MethodHandle iterations, MethodHandle init, MethodHandle body) 指定された数の反復を実行するループを構築します。static MethodHandle
countedLoop
(MethodHandle start, MethodHandle end, MethodHandle init, MethodHandle body) 数値の範囲にわたってカウントするループを構築します。static MethodHandle
doWhileLoop
(MethodHandle init, MethodHandle body, MethodHandle pred) 初期化子、本文および述語からdo-while
ループを構築します。static MethodHandle
dropArguments
(MethodHandle target, int pos, Class<?>... valueTypes) いくつかのダミー引数を破棄してから指定された別のtargetメソッド・ハンドルを呼び出すメソッド・ハンドルを生成します。static MethodHandle
dropArguments
(MethodHandle target, int pos, List<Class<?>> valueTypes) いくつかのダミー引数を破棄してから指定された別のtargetメソッド・ハンドルを呼び出すメソッド・ハンドルを生成します。static MethodHandle
dropArgumentsToMatch
(MethodHandle target, int skip, List<Class<?>> newTypes, int pos) 指定されたパラメータ・タイプ・リストと一致するようにターゲット・メソッド・ハンドルを適応させます。static VarHandle
dropCoordinates
(VarHandle target, int pos, Class<?>... valueTypes) ターゲットのvarハンドルに委譲する前にダミー座標を破棄するvarハンドルを返します。static MethodHandle
dropReturn
(MethodHandle target) ターゲット・ハンドル(もしあれば)の戻り値を削除します。static MethodHandle
empty
(MethodType type) リクエストされた型のメソッド・ハンドルを生成します。引数は無視され、何も実行されず、戻り値の型に応じて適切なデフォルトが返されます。static MethodHandle
exactInvoker
(MethodType type) 特殊なインボーカ・メソッド・ハンドルを生成します(これを使用すれば、指定された型の任意のメソッド・ハンドルを、invokeExact
を使用する場合と同様に呼び出すことができる)。static MethodHandle
explicitCastArguments
(MethodHandle target, MethodType newType) 指定されたメソッド・ハンドルの型を新しい型に適応させるために、引数と戻り値の型の変換をペア単位で行うメソッド・ハンドルを生成します。static MethodHandle
filterArguments
(MethodHandle target, int pos, MethodHandle... filters) ターゲット・メソッド・ハンドルを適応させるため、その1つ以上の引数をそれぞれ固有の単項フィルタ関数を使って前処理したあと、前処理を行った各引数を対応するフィルタ関数の結果で置き換えてターゲットを呼び出します。static VarHandle
filterCoordinates
(VarHandle target, int pos, MethodHandle... filters) 単項フィルタ関数を使用して着信座標値を前処理することで、ターゲット変数ハンドルを適応させます。static MethodHandle
filterReturnValue
(MethodHandle target, MethodHandle filter) ターゲット・メソッド・ハンドルを適応させるため、その戻り値(存在する場合)をフィルタ(別のメソッド・ハンドル)で後処理します。static VarHandle
filterValue
(VarHandle target, MethodHandle filterToTarget, MethodHandle filterFromTarget) フィルタ関数のペアを使用して受信値と送信値を事前処理することで、ターゲット変数ハンドルを適応させます。static MethodHandle
foldArguments
(MethodHandle target, int pos, MethodHandle combiner) ターゲット・メソッド・ハンドルは、指定された位置から始めて、その引数の一部を前処理し、前処理の結果でターゲットをコールして、折り畳まれた引数の直前に元の引数のシーケンスに挿入することによって適応されます。static MethodHandle
foldArguments
(MethodHandle target, MethodHandle combiner) ターゲット・メソッド・ハンドルを適応させるため、その引数のいくつかを前処理したあと、前処理の結果を元の一連の引数内に挿入してターゲットを呼び出します。static MethodHandle
guardWithTest
(MethodHandle test, MethodHandle target, MethodHandle fallback) テスト(boolean値のメソッド・ハンドル)で保護することでターゲット・メソッド・ハンドルを適応させるメソッド・ハンドルを作成します。static MethodHandle
呼出し時に唯一の引数の値を返すメソッド・ハンドルを生成します。static MethodHandle
insertArguments
(MethodHandle target, int pos, Object... values) ターゲット・メソッド・ハンドルの呼出しの前に、1つ以上のバインド引数をメソッド・ハンドルに提供します。static VarHandle
insertCoordinates
(VarHandle target, int pos, Object... values) Varハンドル呼出しの前に、1つ以上の「バインド座標」を持つターゲットvarハンドルを提供します。static MethodHandle
invoker
(MethodType type) 特殊なインボーカ・メソッド・ハンドルを生成します(これを使用すれば、指定された型と互換性のある任意のメソッド・ハンドルを、invoke
を使用する場合と同様に呼び出すことができる)。static MethodHandle
iteratedLoop
(MethodHandle iterator, MethodHandle init, MethodHandle body) Iterator<T>
によって生成された値の範囲にあるループを構築します。static MethodHandles.Lookup
lookup()
呼出し元のすべてのサポートされるバイトコード動作をエミュレートするためのフル機能を持つルックアップ・オブジェクト
を返します。static MethodHandle
loop
(MethodHandle[]... clauses) 反復ごとに更新およびチェックされる複数のループ変数を持つループを表すメソッド・ハンドルを構築します。static MethodHandle
permuteArguments
(MethodHandle target, MethodType newType, int... reorder) 引数の順序を変更することによって、指定されたメソッド・ハンドルの呼出し順序を新しい型に適応させるメソッド・ハンドルを生成します。static VarHandle
permuteCoordinates
(VarHandle target, List<Class<?>> newCoordinates, int... reorder) 新しい座標が指定された座標と一致するように再配列することで、ターゲットのvarハンドルの座標値を適応させるvarハンドルを提供します。static MethodHandles.Lookup
privateLookupIn
(Class<?> targetClass, MethodHandles.Lookup caller) 「プライベート・アクセス」を含む、サポートされているすべてのバイトコード動作をエミュレートするために、ターゲット・クラスのlookup
オブジェクトを返します。static MethodHandles.Lookup
最小の信頼レベルを持つルックアップ・オブジェクト
を返します。static <T extends Member>
TreflectAs
(Class<T> expected, MethodHandle target) 直接メソッド・ハンドルの未チェックの解読を実行します。static MethodHandle
spreadInvoker
(MethodType type, int leadingArgCount) 指定されたtype
の任意のメソッド・ハンドルを呼び出すメソッド・ハンドルを生成しますが、その際、指定された数の末尾の引数が単一の末尾のObject[]
配列で置き換えられます。static MethodHandle
tableSwitch
(MethodHandle fallback, MethodHandle... targets) 表スイッチ・メソッド・ハンドルを作成します。これは、セレクタと呼ばれる特定のターゲット索引に基づいて、ターゲット・メソッド・ハンドルのセットを切り替えるために使用できます。static MethodHandle
throwException
(Class<?> returnType, Class<? extends Throwable> exType) 指定されたexType
の例外をスローするメソッド・ハンドルを生成します。static MethodHandle
tryFinally
(MethodHandle target, MethodHandle cleanup) target
メソッド・ハンドルをtry-finally
ブロックにラップして適応させるメソッド・ハンドルを作成します。static MethodHandle
varHandleExactInvoker
(VarHandle.AccessMode accessMode, MethodType type) 特別な「呼び出しメソッドhandle」を生成します。このメソッドを使用して、関連付けられたアクセス・モード・タイプが指定のタイプと互換性がある任意のVarHandleでシグネチャ-多相アクセス・モード・メソッドを呼び出すことができます。static MethodHandle
varHandleInvoker
(VarHandle.AccessMode accessMode, MethodType type) 特別な「呼び出しメソッドhandle」を生成します。このメソッドを使用して、関連付けられたアクセス・モード・タイプが指定のタイプと互換性がある任意のVarHandleでシグネチャ-多相アクセス・モード・メソッドを呼び出すことができます。static MethodHandle
whileLoop
(MethodHandle init, MethodHandle pred, MethodHandle body) 初期化子、本文および述語からwhile
ループを構築します。static MethodHandle
リクエストされた戻り型の定数メソッド・ハンドルを生成します。このハンドルは、呼び出されるたびにその型のデフォルト値を返します。
-
メソッドの詳細
-
lookup
public static MethodHandles.Lookup lookup()呼出し元のすべてのサポートされるバイトコード動作をエミュレートするためのフル機能を持つルックアップ・オブジェクト
を返します。 これらの機能には、コール元に対する「完全な権限アクセス」が含まれます。 ルックアップ・オブジェクトのファクトリ・メソッドは、呼出し元がバイトコードを介してアクセスするメンバー(protectedおよびprivateのフィールドおよびメソッドを含む)の直接メソッド・ハンドルを作成できます。 このルックアップ・オブジェクトは、元のルックアップ・クラスによって作成され、ORIGINAL
ビットが設定されます。 このルックアップ・オブジェクトは、信頼できるエージェントに委譲可能な1つの機能です。 信頼できないコードからアクセス可能な場所に格納しないでください。このメソッドは呼出し元依存です。つまり、呼出し元ごとに異なる値を返す可能性があります。 スタック(例、JNIアタッチ・スレッドから直接コールされる場合)にコール元フレームがないコンテキストから
MethodHandles.lookup
がコールされると、IllegalCallerException
がスローされます。 このようなコンテキストでlookup object
を取得するには、コール元として暗黙的に識別される補助クラスを使用するか、かわりにpublicLookup()
を使用して権限の低いルックアップを取得します。- 戻り値:
- originalおよび「完全な権限アクセス」での、このメソッドの呼出し側のルックアップ・オブジェクト。
- 例外:
IllegalCallerException
- スタック上に呼び出し元フレームがない場合。
-
publicLookup
public static MethodHandles.Lookup publicLookup()最小の信頼レベルを持つルックアップ・オブジェクト
を返します。 参照にはUNCONDITIONAL
モードがあります。 これは、無条件にエクスポートされるパッケージ内のパブリック・クラスのパブリック・メンバーへのメソッド・ハンドルの作成にのみ使用できます。単に慣例により、このルックアップ・オブジェクトのルックアップ・クラスは、
Object
になります。- APIのノート:
- Objectの使用は従来型であり、ルックアップ・モードは制限されているため、Object、そのパッケージまたはそのモジュールの内部に特別なアクセスは提供されません。
UNCONDITIONAL
モードでは、この公開された参照オブジェクトまたはその他の参照オブジェクトは、可読性を想定しています。 したがって、ルックアップ・クラスを使用してルックアップ・コンテキストが決定されません。ディスカッション: ルックアップ・クラスは、
publicLookup().in(C.class)
形式の式を使用して、他の任意のクラスC
に変更できます。 publicルックアップ・オブジェクトは常にセキュリティ・マネージャ・チェックが適用されます。 また、呼出し元依存メソッドにアクセスすることもできません。 - 戻り値:
- 最小限の信頼されるルックアップ・オブジェクト
-
privateLookupIn
public static MethodHandles.Lookup privateLookupIn(Class<?> targetClass, MethodHandles.Lookup caller) throws IllegalAccessException 「プライベート・アクセス」を含む、サポートされているすべてのバイトコード動作をエミュレートするために、ターゲット・クラスのlookup
オブジェクトを返します。 返された参照オブジェクトは、モジュールおよびパッケージ内のクラス、およびそれらのクラスのメンバーへのアクセスを提供できます。ただし、Javaアクセス制御の通常のルールの範囲外では、モジュラ「深い反射」のより許容性の高いルールに準拠します。モジュール
M1
では、Lookup
オブジェクトとして指定されたコール元は、次のすべての条件がtrue
の場合にのみ、モジュールM2
およびターゲット・クラスのパッケージの深い反映が許可されます:- セキュリティ・マネージャが存在する場合は、
checkPermission
メソッドが呼び出されてReflectPermission("suppressAccessChecks")
がチェックされ、正常に戻す必要があります。 - コール元参照オブジェクトには「完全な権限アクセス」が必要です。 具体的には、次のようになります。
- ターゲット・クラスは、プリミティブまたは配列クラスではなく、適切なクラスでなければなりません。 (したがって、
M2
は適切に定義されています。) - コール元モジュール
M1
がターゲット・モジュールM2
と異なる場合、次の両方がtrueである必要があります:
前述のいずれかのチェックに違反している場合、このメソッドは例外を出力して失敗します。
それ以外の場合、
M1
とM2
が同じモジュールであれば、このメソッドは「完全な権限アクセス」とnull
の以前のルックアップ・クラスを使用してtargetClass
上のLookup
を返します。それ以外の場合、
M1
とM2
は2つの異なるモジュールです。 このメソッドは、コール元のルックアップ・クラスをPRIVATE
アクセス権を持つ新しい以前のルックアップ・クラスとして記録し、MODULE
アクセス権を持たないLookup
をtargetClass
で戻します。結果の
Lookup
オブジェクトには、ORIGINAL
アクセス権がありません。- APIのノート:
- このメソッドによって返される
Lookup
オブジェクトは、targetClass
の実行時パッケージで「クラスの定義」に許可されます。 パッケージを別のモジュールに開く際には、targetClass
のモジュール内の他のメンバーと同じ完全な権限アクセス権を持つように注意してください。 - パラメータ:
targetClass
- ターゲット・クラスcaller
- 呼び出し元参照オブジェクト- 戻り値:
- プライベート・アクセスを持つターゲット・クラスのルックアップ・オブジェクト
- 例外:
IllegalArgumentException
-targetClass
がプリミティブ・タイプ、voidまたは配列クラスの場合NullPointerException
-targetClass
またはcaller
がnull
の場合SecurityException
- セキュリティ・マネージャによって拒否された場合IllegalAccessException
- 上に指定した他のアクセス・チェックのいずれかが失敗した場合- 導入されたバージョン:
- 9
- 関連項目:
- セキュリティ・マネージャが存在する場合は、
-
classData
public static <T> T classData(MethodHandles.Lookup caller, String name, Class<T> type) throws IllegalAccessException 指定されたcaller
ルックアップ・オブジェクトまたはnull
のルックアップ・クラスに関連付けられた「クラス・データ」を返します。クラス・データを含む非表示クラスは、
Lookup::defineHiddenClassWithClassData
をコールすることで作成できます。 このメソッドにより、指定されたcaller
ルックアップ・オブジェクトのルックアップ・クラスの静的クラス・イニシャライザが実行されます(初期化されていない場合)。Lookup::defineHiddenClass
によって作成された非表示クラスと非表示でないクラスには、クラス・データはありません。これらのクラスのルックアップ・オブジェクトでこのメソッドが呼び出されると、null
が返されます。クラス・データを取得するには、このルックアップの「ルックアップ・モード」に「元のアクセス」が必要です。
- APIのノート:
- このメソッドは、動的に計算された定数のブートストラップ・メソッドとしてコールできます。 フレームワークでは、クラス・データ(
Class
オブジェクトやMethodHandle
オブジェクトなど)を使用して非表示クラスを作成できます。 クラス・データには、元の呼出し側によって作成されたルックアップ・オブジェクトからのみアクセスできますが、同じネスト内の他のメンバーからはアクセスできません。 フレームワークがクラス・データを介してセキュリティ上重要なオブジェクトを非表示クラスに渡す場合は、他のネストされたオブジェクトからアクセス可能なprivate staticフィールドにクラス・データを格納するのではなく、クラス・データの値を動的に計算された定数としてロードすることをお薦めします。 - 型パラメータ:
T
- クラス・データ・オブジェクトのキャスト先の型- パラメータ:
caller
- 操作を実行するクラスを説明する参照コンテキスト(通常はJVMによってスタック)name
-ConstantDescs.DEFAULT_NAME
("_"
)である必要がありますtype
- クラス・データの型- 戻り値:
- ルックアップ・クラスに存在する場合はクラス・データの値、そうでない場合は
null
- 例外:
IllegalArgumentException
- 名前が"_"
でない場合IllegalAccessException
- ルックアップ・コンテキストにoriginalアクセス権がない場合ClassCastException
- クラス・データを特定のtype
に変換できない場合NullPointerException
-caller
またはtype
引数がnull
の場合- Java Virtual Machine仕様を参照してください:
-
5.5 初期化
- 導入されたバージョン:
- 16
- 関連項目:
-
classDataAt
public static <T> T classDataAt(MethodHandles.Lookup caller, String name, Class<T> type, int index) throws IllegalAccessException 指定されたcaller
ルックアップ・オブジェクトのルックアップ・クラスに関連付けられているクラス・データがList
の場合、「クラス・データ」の指定された索引にある要素を返します。 クラス・データがこのルックアップ・クラスにない場合、このメソッドはnull
を返します。クラス・データを含む非表示クラスは、
Lookup::defineHiddenClassWithClassData
をコールすることで作成できます。 このメソッドにより、指定されたcaller
ルックアップ・オブジェクトのルックアップ・クラスの静的クラス・イニシャライザが実行されます(初期化されていない場合)。Lookup::defineHiddenClass
によって作成された非表示クラスと非表示でないクラスには、クラス・データはありません。これらのクラスのルックアップ・オブジェクトでこのメソッドが呼び出されると、null
が返されます。クラス・データを取得するには、このルックアップの「ルックアップ・モード」に「元のアクセス」が必要です。
- APIのノート:
- このメソッドは、動的に計算された定数のブートストラップ・メソッドとしてコールできます。 フレームワークでは、クラス・データを含む非表示クラスを作成できます。たとえば、複数のオブジェクトを含む
List.of(o1, o2, o3....)
を作成し、このメソッドを使用して特定の索引で複数の要素をロードできます。 クラス・データには、元の呼出し側によって作成されたルックアップ・オブジェクトからのみアクセスできますが、同じネスト内の他のメンバーからはアクセスできません。 フレームワークがクラス・データを介してセキュリティ上重要なオブジェクトを非表示クラスに渡す場合は、他のネストされたオブジェクトからアクセス可能なprivate staticフィールドにクラス・データを格納するのではなく、クラス・データの値を動的に計算された定数としてロードすることをお薦めします。 - 型パラメータ:
T
- 結果オブジェクトのキャスト先の型- パラメータ:
caller
- 操作を実行するクラスを説明する参照コンテキスト(通常はJVMによってスタック)name
-ConstantDescs.DEFAULT_NAME
("_"
)である必要がありますtype
- クラス・データ内の指定されたインデックスにある要素の型index
- クラス・データ内の要素の索引- 戻り値:
- クラス・データが存在する場合は、クラス・データ内の指定されたインデックスにある要素。それ以外の場合は
null
- 例外:
IllegalArgumentException
- 名前が"_"
でない場合IllegalAccessException
- ルックアップ・コンテキストにoriginalアクセス権がない場合ClassCastException
- クラス・データをList
に変換できない場合、または指定された索引の要素を指定された型に変換できない場合IndexOutOfBoundsException
- 索引が範囲外の場合NullPointerException
-caller
またはtype
引数がnull
の場合、または指定された索引の要素がnull
であるためにアン・ボクシング演算が失敗した場合- 導入されたバージョン:
- 16
- 関連項目:
-
reflectAs
public static <T extends Member> T reflectAs(Class<T> expected, MethodHandle target) 直接メソッド・ハンドルの未チェックの解読を実行します。 結果は、ユーザーがターゲット・メソッド・ハンドルを解決するのに十分な機能を持つルックアップ・オブジェクトを取得し、ターゲットでLookup.revealDirect
を呼び出してシンボリック参照を取得し、MethodHandleInfo.reflectAs
を呼び出してシンボリック参照をメンバーに解決したかのようになります。セキュリティ・マネージャが存在する場合は、その
checkPermission
メソッドがReflectPermission("suppressAccessChecks")
アクセス権で呼び出されます。- 型パラメータ:
T
- 結果に期待する型(Member
またはサブタイプ)- パラメータ:
expected
- 期待する結果型T
を表すクラス・オブジェクトtarget
- シンボリック参照コンポーネントに解決する直接メソッド・ハンドル- 戻り値:
- メソッド、コンストラクタまたはフィールド・オブジクトへの参照
- 例外:
SecurityException
- 呼出し元にsetAccessible
を呼び出す権限が与えられていない場合NullPointerException
- どちらかの引数がnull
の場合IllegalArgumentException
- ターゲットが直接メソッド・ハンドルでない場合ClassCastException
- メンバーが期待される型でない場合- 導入されたバージョン:
- 1.8
-
arrayConstructor
public static MethodHandle arrayConstructor(Class<?> arrayClass) throws IllegalArgumentException anewarray
バイトコードの場合と同様に、必要な型の配列を構築するメソッド・ハンドルを生成します。 メソッド・ハンドルの戻り型は配列型です。 唯一の引数の型は、配列のサイズを指定するint
になります。返されたメソッド・ハンドルが負の配列サイズで呼び出された場合は、
NegativeArraySizeException
がスローされます。- パラメータ:
arrayClass
- 配列の型- 戻り値:
- 指定された型の配列を作成できるメソッド・ハンドル
- 例外:
NullPointerException
- 引数がnull
の場合IllegalArgumentException
-arrayClass
が配列型でない場合- Java Virtual Machine仕様を参照してください:
-
6.5
anewarray
命令 - 導入されたバージョン:
- 9
- 関連項目:
-
arrayLength
public static MethodHandle arrayLength(Class<?> arrayClass) throws IllegalArgumentException arraylength
バイトコードの場合と同様に、配列の長さを返すメソッド・ハンドルを生成します。 メソッド・ハンドルの型は戻り型としてint
を持ち、その唯一の引数は配列型になります。返されたメソッド・ハンドルが
null
配列参照で呼び出されると、NullPointerException
がスローされます。- パラメータ:
arrayClass
- 配列の型- 戻り値:
- 指定された配列型の配列の長さを取得できるメソッド・ハンドル
- 例外:
NullPointerException
- 引数がnull
の場合IllegalArgumentException
- arrayClassが配列型でない場合- Java Virtual Machine仕様を参照してください:
-
6.5
arraylength
命令 - 導入されたバージョン:
- 9
-
arrayElementGetter
public static MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException aaload
バイトコードの場合と同様に、配列の要素に対する読み取りアクセスを提供するメソッド・ハンドルを生成します。 メソッド・ハンドルの型に含まれる戻り値の型は、配列の要素の型になります。 その最初の引数は配列の型、2番目の引数はint
になります。返されたメソッド・ハンドルが呼び出されると、配列参照と配列インデックスがチェックされます。 配列リファレンスが
null
の場合はNullPointerException
がスローされ、インデックスが負の場合または配列の長さ以上の場合はArrayIndexOutOfBoundsException
がスローされます。- パラメータ:
arrayClass
- 配列の型- 戻り値:
- 指定された配列型から値をロードできるメソッド・ハンドル
- 例外:
NullPointerException
- 引数がnullの場合IllegalArgumentException
- arrayClassが配列型でない場合- Java Virtual Machine仕様を参照してください:
-
6.5
aaload
命令
-
arrayElementSetter
public static MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException astore
バイトコードの場合と同様に、配列の要素への書き込みアクセスを与えるメソッド・ハンドルを生成します。 このメソッド・ハンドルの型に含まれる戻り値の型は、voidになります。 その最後の引数は、配列の要素の型になります。 最初と2番目の引数は、配列の型とintになります。返されたメソッド・ハンドルが呼び出されると、配列参照と配列インデックスがチェックされます。 配列リファレンスが
null
の場合はNullPointerException
がスローされ、インデックスが負の場合または配列の長さ以上の場合はArrayIndexOutOfBoundsException
がスローされます。- パラメータ:
arrayClass
- 配列のクラス- 戻り値:
- 配列型に値を格納できるメソッド・ハンドル
- 例外:
NullPointerException
- 引数がnullの場合IllegalArgumentException
- arrayClassが配列型でない場合- Java Virtual Machine仕様を参照してください:
-
6.5
aastore
命令
-
arrayElementVarHandle
public static VarHandle arrayElementVarHandle(Class<?> arrayClass) throws IllegalArgumentException 型arrayClass
の配列の要素にアクセスするVarHandleを生成します。 VarHandleの変数型はarrayClass
のコンポーネント型で、座標型のリストは(arrayClass, int)
です。ここで、int
座標型は配列への索引である引数に対応します。返されたVarHandleの特定のアクセス・モードは、次の条件ではサポートされません:
- コンポーネント・タイプが
byte
,short
,char
,int
,long
,float
またはdouble
以外の場合、数値アトミック更新アクセス・モードはサポートされていません。 - コンポーネント・タイプが
boolean
、byte
、short
、char
、int
またはlong
以外の場合、ビット単位のアトミック更新アクセス・モードはサポートされません。
コンポーネント型が
float
またはdouble
の場合、数値およびアトミック更新アクセス・モードはビット単位の表現(それぞれFloat.floatToRawIntBits(float)
とDouble.doubleToRawLongBits(double)
を参照してください)を使用して値を比較します。返された
VarHandle
が呼び出されると、配列参照と配列インデックスがチェックされます。 配列リファレンスがnull
の場合はNullPointerException
がスローされ、インデックスが負の場合または配列の長さ以上の場合はArrayIndexOutOfBoundsException
がスローされます。- APIのノート:
- 数値およびアトミック更新アクセス・モードで実行される
float
値またはdouble
値のビット単位比較は、プリミティブ==
演算子およびFloat.equals(java.lang.Object)
およびDouble.equals(java.lang.Object)
メソッドとは異なります。特に、NaN値の比較または-0.0
と+0.0
の比較については異なります。 この操作が予期せず失敗する可能性があるため、これらの値との比較および設定または比較および交換操作の実行時には注意が必要です。 JavaではNaN
とみなされるNaN値は多数ありますが、Javaで提供されるIEEE 754浮動小数点演算では区別できません。 予期される値または証人値がNaN値で、(おそらくプラットフォーム固有の方法で)を別のNaN値に変換し、異なるビット単位の表現(詳細はFloat.intBitsToFloat(int)
またはDouble.longBitsToDouble(long)
を参照してください)を持つ場合、操作の失敗が発生する可能性があります。 値-0.0
および+0.0
は、ビット単位の表現は異なりますが、プリミティブ==
演算子を使用するときは等しいとみなされます。 たとえば、数値アルゴリズムが予期される値を-0.0
と計算し、以前に証人値を+0.0
と計算した場合、操作の失敗が発生する可能性があります。 - パラメータ:
arrayClass
-T[]
型の配列のクラス- 戻り値:
- 配列の要素にアクセスするVarHandle
- 例外:
NullPointerException
- arrayClassがnullの場合IllegalArgumentException
- arrayClassが配列型でない場合- 導入されたバージョン:
- 9
- コンポーネント・タイプが
-
byteArrayViewVarHandle
public static VarHandle byteArrayViewVarHandle(Class<?> viewArrayClass, ByteOrder byteOrder) throws IllegalArgumentException int[]
やlong[]
など、異なるプリミティブ配列型であるかのように見えるbyte[]
配列の要素へのアクセス権を付与するVarHandleを生成します。 VarHandleの変数型はviewArrayClass
のコンポーネント型で、座標型のリストは(byte[], int)
です。ここで、int
座標型はbyte[]
配列への索引である引数に対応します。 戻されたVarHandleは、byte[]
配列内の索引のバイトにアクセスし、指定されたエンディアンに従って、viewArrayClass
のコンポーネント型の値との間でバイトを構成します。サポートされているコンポーネント・タイプ(変数の型)は、
short
,char
,int
,long
,float
およびdouble
です。インデックスが
0
より小さい場合、またはbyte[]
配列の長さからT
のサイズ(バイト単位)を引いた値より大きい場合、特定のインデックスでバイトにアクセスすると、ArrayIndexOutOfBoundsException
になります。配列および索引に関連付けられている基礎となるメモリー・アドレス(
A
)に関して、T
に対する索引のバイト・アクセスの整列または整列不良が考えられます。 アクセスが整列していない場合、get
およびset
アクセス・モード以外のアクセスは、IllegalStateException
になります。 そのような場合、アトミック・アクセスは、A
のGCDとT
のサイズ(バイト単位)を分割する2の最大の累乗に関してのみ保証されます。 アクセスが整列されている場合、次のアクセス・モードがサポートされ、アトミック・アクセスをサポートすることが保証されています:- すべての
T
の読取り書込みアクセス・モード(long
の場合はアクセス・モードget
およびset
、32ビット・プラットフォームの場合はdouble
を除く)。 int
,long
,float
またはdouble
のアトミック更新アクセス・モード。 (JDKの将来のメジャー・プラットフォーム・リリースでは、現在サポートされていない特定のアクセス・モードの追加タイプがサポートされる場合があります。)int
およびlong
の数値アトミック更新アクセス・モード。 (JDKの将来のメジャー・プラットフォーム・リリースでは、現在サポートされていない特定のアクセス・モードに対して追加の数値型をサポートする場合があります。)int
とlong
のビット単位アトミック更新アクセス・モード。 (JDKの将来のメジャー・プラットフォーム・リリースでは、現在サポートされていない特定のアクセス・モードに対して追加の数値型をサポートする場合があります。)
整列されていないアクセス(したがって原子性の保証)は、特定の配列を操作せずに
byte[]
配列に対して決定できます。index
、T
および対応するボックス・タイプT_BOX
を指定すると、次のように不整合が決定されます:int sizeOfT = T_BOX.BYTES; // size in bytes of T int misalignedAtZeroIndex = ByteBuffer.wrap(new byte[0]). alignmentOffset(0, sizeOfT); int misalignedAtIndex = (misalignedAtZeroIndex + index) % sizeOfT; boolean isMisaligned = misalignedAtIndex != 0;
変数の型が
float
またはdouble
の場合、アトミック更新アクセス・モードはビット単位の表現(それぞれFloat.floatToRawIntBits(float)
とDouble.doubleToRawLongBits(double)
を参照してください)を使用して値を比較します。- パラメータ:
viewArrayClass
-T
型のコンポーネント・タイプを持つビュー配列クラスbyteOrder
- 基礎となるbyte
配列に格納される、ビュー配列要素のエンディアン- 戻り値:
byte[]
配列の要素にアクセスするVarHandleは、ビュー配列クラスのコンポーネント型に対応する要素として見なされます- 例外:
NullPointerException
- viewArrayClassまたはbyteOrderがnullの場合IllegalArgumentException
- viewArrayClassが配列型でない場合UnsupportedOperationException
- viewArrayClassのコンポーネント型が変数型としてサポートされていない場合- 導入されたバージョン:
- 9
- すべての
-
byteBufferViewVarHandle
public static VarHandle byteBufferViewVarHandle(Class<?> viewArrayClass, ByteOrder byteOrder) throws IllegalArgumentException int[]
またはlong[]
など、byte
の要素にアクセスするVarHandleを生成します。これは、ByteBuffer
の要素と異なるプリミティブ・コンポーネント型の要素の配列であるかのように見えます。 VarHandleの変数型はviewArrayClass
のコンポーネント型で、座標型のリストは(ByteBuffer, int)
です。ここで、int
座標型はbyte[]
配列への索引である引数に対応します。 戻されたVarHandleは、ByteBuffer
内の索引のバイトにアクセスし、指定されたエンディアンに従って、viewArrayClass
のコンポーネント型の値との間でバイトを構成します。サポートされているコンポーネント・タイプ(変数の型)は、
short
,char
,int
,long
,float
およびdouble
です。ByteBuffer
が読取り専用の場合、アクセスは読取りアクセス・モード以外のものに対してReadOnlyBufferException
になります。インデックスが
0
より小さい場合、またはByteBuffer
制限からT
のサイズ(バイト単位)を引いた値より大きい場合、特定のインデックスでバイトにアクセスすると、IndexOutOfBoundsException
になります。索引のバイト・アクセスは、
ByteBuffer
および索引に関連付けられている基礎となるメモリー・アドレス(A
)に関して、T
に対して整列または整列されていない場合があります。 アクセスが整列していない場合、get
およびset
アクセス・モード以外のアクセスは、IllegalStateException
になります。 そのような場合、アトミック・アクセスは、A
のGCDとT
のサイズ(バイト単位)を分割する2の最大の累乗に関してのみ保証されます。 アクセスが整列されている場合、次のアクセス・モードがサポートされ、アトミック・アクセスをサポートすることが保証されています:- すべての
T
の読取り書込みアクセス・モード(long
の場合はアクセス・モードget
およびset
、32ビット・プラットフォームの場合はdouble
を除く)。 int
,long
,float
またはdouble
のアトミック更新アクセス・モード。 (JDKの将来のメジャー・プラットフォーム・リリースでは、現在サポートされていない特定のアクセス・モードの追加タイプがサポートされる場合があります。)int
およびlong
の数値アトミック更新アクセス・モード。 (JDKの将来のメジャー・プラットフォーム・リリースでは、現在サポートされていない特定のアクセス・モードに対して追加の数値型をサポートする場合があります。)int
とlong
のビット単位アトミック更新アクセス・モード。 (JDKの将来のメジャー・プラットフォーム・リリースでは、現在サポートされていない特定のアクセス・モードに対して追加の数値型をサポートする場合があります。)
ByteBuffer
、bb
(直接的またはその他の方法で)、index
、T
および対応するボックス・タイプ(T_BOX
)に対して、不整合アクセス(原子性保証)を決定できます:int sizeOfT = T_BOX.BYTES; // size in bytes of T ByteBuffer bb = ... int misalignedAtIndex = bb.alignmentOffset(index, sizeOfT); boolean isMisaligned = misalignedAtIndex != 0;
変数の型が
float
またはdouble
の場合、アトミック更新アクセス・モードはビット単位の表現(それぞれFloat.floatToRawIntBits(float)
とDouble.doubleToRawLongBits(double)
を参照してください)を使用して値を比較します。- パラメータ:
viewArrayClass
-T
型のコンポーネント・タイプを持つビュー配列クラスbyteOrder
- 基礎となるByteBuffer
(これはByteBuffer
のエンディアンを上書きすることに注意してください)に格納される、ビュー配列要素のエンディアン- 戻り値:
ByteBuffer
の要素にアクセスするVarHandleは、ビュー配列クラスのコンポーネントの型に対応する要素のように見なされます- 例外:
NullPointerException
- viewArrayClassまたはbyteOrderがnullの場合IllegalArgumentException
- viewArrayClassが配列型でない場合UnsupportedOperationException
- viewArrayClassのコンポーネント型が変数型としてサポートされていない場合- 導入されたバージョン:
- 9
- すべての
-
spreadInvoker
public static MethodHandle spreadInvoker(MethodType type, int leadingArgCount) 指定されたtype
の任意のメソッド・ハンドルを呼び出すメソッド・ハンドルを生成しますが、その際、指定された数の末尾の引数が単一の末尾のObject[]
配列で置き換えられます。 結果となるインボーカは、次の引数を持つメソッド・ハンドルです。- 単一の
MethodHandle
ターゲット - 0個以上の先頭の値(個数は
leadingArgCount
) - 末尾の引数を含む
Object[]
配列
インボーカがそのターゲットを呼び出す方法は、示された
type
を使用したinvoke
の呼出しに似ています。 つまりその動作は、ターゲットの型が指定されたtype
と完全に等しい場合はinvokeExact
のようになり、それ以外の場合は、asType
を使ってターゲットを必要なtype
に変換するような動作になります。返されるインボーカの型は、指定された
type
ではなく、最初のleadingArgCount
個を除くすべてのパラメータが単一のObject[]
型配列で置き換えられたものとなり、これが最後のパラメータになります。インボーカはそのターゲットを呼び出す前に、最後の配列を分配し、参照キャストを必要に応じて適用するほか、プリミティブ引数のアンボクシングやワイドニングを行います。 インボーカが呼び出されるときに、渡される配列引数が正しい数の要素を持たない場合、インボーカはターゲットを呼び出すかわりに
IllegalArgumentException
をスローします。このメソッドは次のコードと同等です(ただし、効率はおそらくこのメソッドのほうが高い)。
MethodHandle invoker = MethodHandles.invoker(type); int spreadArgCount = type.parameterCount() - leadingArgCount; invoker = invoker.asSpreader(Object[].class, spreadArgCount); return invoker;
- パラメータ:
type
- 目的となるターゲットの型leadingArgCount
- ターゲットに無変更で渡される固定引数の数- 戻り値:
- 指定された型の任意のメソッド・ハンドルの呼出しに適したメソッド・ハンドル
- 例外:
NullPointerException
-type
がnullである場合IllegalArgumentException
-leadingArgCount
が0からtype.parameterCount()
(含む)までの範囲でない場合、または結果のメソッド・ハンドルの型のパラメータ数が多すぎる場合
- 単一の
-
exactInvoker
public static MethodHandle exactInvoker(MethodType type) 特殊なインボーカ・メソッド・ハンドルを生成します(これを使用すれば、指定された型の任意のメソッド・ハンドルを、invokeExact
を使用する場合と同様に呼び出すことができる)。 結果となるインボーカの型は、MethodHandle
型の追加の先頭の引数を1つ受け取る点を除けば、目的の型とまったく等しくなります。このメソッドは次のコードと同等です(ただし、効率はおそらくこのメソッドのほうが高い)。
publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)
解説: インボーカ・メソッド・ハンドルは、未知の型のメソッド・ハンドル変数を操作する場合に役立つ可能性があります。 たとえば、メソッド・ハンドル変数
M
へのinvokeExact
呼出しをエミュレートするには、その型T
を抽出し、T
用のインボーカ・メソッドX
を検索し、インボーカ・メソッドをX.invoke(T, A...)
のように呼び出します。 (型T
が未知であるため、X.invokeExact
の呼出しは機能しない。) 分配や収集などの引数変換が必要な場合は、それらをインボーカX
に一度だけ適用しておけば、M
のさまざまなメソッド・ハンドル値(ただしX
の型と互換性があるものにかぎる)で再利用できます。(ノート: Core Reflection API経由でインボーカ・メソッドを使用することはできません。 宣言された
invokeExact
またはinvoke
メソッドでjava.lang.reflect.Method.invokeを呼び出そうとすると、UnsupportedOperationException
が発行されます。)このメソッドでは、リフレクションやセキュリティに関する例外はスローされません。
- パラメータ:
type
- 目的となるターゲットの型- 戻り値:
- 指定された型の任意のメソッド・ハンドルの呼出しに適したメソッド・ハンドル
- 例外:
IllegalArgumentException
- 結果のメソッド・ハンドルの型のパラメータ数が多すぎる場合
-
invoker
public static MethodHandle invoker(MethodType type) 特殊なインボーカ・メソッド・ハンドルを生成します(これを使用すれば、指定された型と互換性のある任意のメソッド・ハンドルを、invoke
を使用する場合と同様に呼び出すことができる)。 結果となるインボーカの型は、MethodHandle
型の追加の先頭の引数を1つ受け取る点を除けば、目的の型とまったく等しくなります。ターゲットが期待される型と異なっている場合、インボーカはそのターゲットを呼び出す前に、
asType
の場合と同じように、参照キャストを必要に応じて適用するほか、プリミティブ値のボクシング、アンボクシング、またはワイドニングを行います。 同様に、戻り値も必要に応じて変換されます。 ターゲットが可変引数メソッド・ハンドルの場合は、やはりasType
の場合と同じように、必要な引数変換が行われます。このメソッドは次のコードと同等です(ただし、効率はおそらくこのメソッドのほうが高い)。
publicLookup().findVirtual(MethodHandle.class, "invoke", type)
ディスカッション: 一般的なメソッド型は、
Object
引数および戻り値のみを言及するものです。 そのような型のインボーカは、引数の数が汎用型と同じメソッド・ハンドルであれば任意のものを呼び出すことができます。(ノート: Core Reflection API経由でインボーカ・メソッドを使用することはできません。 宣言された
invokeExact
またはinvoke
メソッドでjava.lang.reflect.Method.invokeを呼び出そうとすると、UnsupportedOperationException
が発行されます。)このメソッドでは、リフレクションやセキュリティに関する例外はスローされません。
- パラメータ:
type
- 目的となるターゲットの型- 戻り値:
- 指定された型に変換可能な任意のメソッド・ハンドルの呼出しに適したメソッド・ハンドル
- 例外:
IllegalArgumentException
- 結果のメソッド・ハンドルの型のパラメータ数が多すぎる場合
-
varHandleExactInvoker
public static MethodHandle varHandleExactInvoker(VarHandle.AccessMode accessMode, MethodType type) 特別な「呼び出しメソッドhandle」を生成します。このメソッドを使用して、関連付けられたアクセス・モード・タイプが指定のタイプと互換性がある任意のVarHandleでシグネチャ-多相アクセス・モード・メソッドを呼び出すことができます。 結果の呼出し側は、VarHandle
型の追加の先行引数を受け入れることを除き、目的の型と完全に等しい型を持ちます。- パラメータ:
accessMode
- VarHandleアクセス・モードtype
- 目的となるターゲットの型- 戻り値:
- アクセス・モード・タイプが指定されたタイプのVarHandleのアクセス・モード・メソッドの呼出しに適したメソッド・ハンドル。
- 導入されたバージョン:
- 9
-
varHandleInvoker
public static MethodHandle varHandleInvoker(VarHandle.AccessMode accessMode, MethodType type) 特別な「呼び出しメソッドhandle」を生成します。このメソッドを使用して、関連付けられたアクセス・モード・タイプが指定のタイプと互換性がある任意のVarHandleでシグネチャ-多相アクセス・モード・メソッドを呼び出すことができます。 結果の呼出し側は、VarHandle
型の追加の先行引数を受け入れることを除き、目的の型と完全に等しい型を持ちます。ターゲットを起動する前に、アクセス・モード・タイプが所定の型と異なる場合、実行者は、
asType
のように、必要に応じて参照キャストを適用し、ボックス、アンボックスまたはワイド・プリミティブ値を適用します。 同様に、戻り値も必要に応じて変換されます。このメソッドは、次のコードと同じです。(より効率的かもしれませんが):
publicLookup().findVirtual(VarHandle.class, accessMode.name(), type)
- パラメータ:
accessMode
- VarHandleアクセス・モードtype
- 目的となるターゲットの型- 戻り値:
- アクセス・モード・タイプが指定された型に変換可能な任意のVarHandleのアクセス・モード・メソッドの呼出しに適したメソッド・ハンドル。
- 導入されたバージョン:
- 9
-
explicitCastArguments
public static MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) 指定されたメソッド・ハンドルの型を新しい型に適応させるために、引数と戻り値の型の変換をペア単位で行うメソッド・ハンドルを生成します。 元の型と新しい型は同じ数の引数を備えている必要があります。 結果のメソッド・ハンドルが目的の新しい型と等しい型を報告することが、保証されます。元の型と新しい型が等しい場合はターゲットを返します。
MethodHandle.asType
の場合と同じ変換が許可されるほか、それらの変換が失敗した場合には、いくつかの追加の変換も適用されます。asType
で行われる変換の前に、あるいはその代わりに、次のいずれかの変換が可能であれば適用されます(T0、T1は型)。- T0とT1が参照であり、T1がインタフェース型である場合は、型T0の値がキャストなしでT1として渡されます。 (インタフェースのこの扱いは、バイトコード・ベリファイアの使用法に従ったものです。)
- T0がbooleanでT1が別のプリミティブの場合、booleanがバイト値に変換されます(trueは1、falseは0)。 (この扱いは、バイトコード・ベリファイアの使用法に従ったものです。)
- T1がブールで、T0が別のプリミティブである場合、T0はJavaキャスト変換(JLS 5.5)を介してバイトに変換され、結果の低順序ビットは
(x & 1) != 0
のようにテストされます。 - T0およびT1がブール以外のプリミティブである場合、Javaキャスト変換(JLS 5.5)が適用されます。 (具体的には、ワイドニングやナローイングによってT0がT1に変換される。)
- T0が参照であり、プリミティブをT1する場合、実行時にボックス化解除変換が適用され、プリミティブ値にJavaキャスト変換(JLS 5.5)が続く可能性があり、その後にロー・オーダー・ビットをテストしてバイトからブールへの変換が続きます。
- T0が参照でT1がプリミティブの場合、実行時に参照がnullであれば、値ゼロが導入されます。
- パラメータ:
target
- 引数の型を調整したあとに呼び出すメソッド・ハンドルnewType
- 新しいメソッド・ハンドルの期待される型- 戻り値:
- 必要な引数変換をすべて実行したあとでターゲットに委譲し、必要なあらゆる戻り値変換の手配も行うメソッド・ハンドル
- 例外:
NullPointerException
- どちらかの引数がnullの場合WrongMethodTypeException
- 変換できない場合- 関連項目:
-
permuteArguments
public static MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) 引数の順序を変更することによって、指定されたメソッド・ハンドルの呼出し順序を新しい型に適応させるメソッド・ハンドルを生成します。 結果のメソッド・ハンドルが目的の新しい型と等しい型を報告することが、保証されます。指定された配列によって並べ替えが制御されます。 入力パラメータの数(値
newType.parameterCount()
)を#I
、出力パラメータの数(値target.type().parameterCount()
)を#O
とします。 このとき、並べ替え配列の長さは#O
、各要素は#I
より小さい負でない数でなければいけません。#O
より小さいすべてのN
について、N
番目の出力引数はI
番目の入力引数から取られます(I
はreorder[N]
)。引数や戻り値の変換は一切適用されません。 各入力引数の型(
newType
によって決定される)は、ターゲット・メソッド・ハンドルの対応する1つまたは複数の出力パラメータの型と同一でなければいけません。newType
の戻り値の型は、元のターゲットの戻り値の型と同一でなければいけません。並べ替え配列では、実際の入れ替えを指定する必要はありません。 配列内でインデックスが複数回現れる入力引数は複製され、配列内でインデックスが現れない入力引数は除去されます。
dropArguments
の場合と同様に、配列の順序変更で記述されていない着信引数は、newType
によってのみ決定される任意の型です。import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodType.*; ... MethodType intfn1 = methodType(int.class, int.class); MethodType intfn2 = methodType(int.class, int.class, int.class); MethodHandle sub = ... (int x, int y) -> (x-y) ...; assert(sub.type().equals(intfn2)); MethodHandle sub1 = permuteArguments(sub, intfn2, 0, 1); MethodHandle rsub = permuteArguments(sub, intfn2, 1, 0); assert((int)rsub.invokeExact(1, 100) == 99); MethodHandle add = ... (int x, int y) -> (x+y) ...; assert(add.type().equals(intfn2)); MethodHandle twice = permuteArguments(add, intfn1, 0, 0); assert(twice.type().equals(intfn1)); assert((int)twice.invokeExact(21) == 42);
ノート: 元のターゲット・メソッド・ハンドルであっても、結果のアダプタは決して可変メソッド・ハンドルではありません。
- パラメータ:
target
- 引数を並べ替えたあとで呼び出すメソッド・ハンドルnewType
- 新しいメソッド・ハンドルの期待される型reorder
- 並べ替えを制御するインデックス配列- 戻り値:
- 未使用の引数を破棄し、ほかの引数の移動や複製を行ったあとでターゲットに委譲するメソッド・ハンドル
- 例外:
NullPointerException
- いずれかの引数がnullの場合IllegalArgumentException
- インデックス配列の長さがターゲットの引数長と等しくない場合、またはインデックス配列に、newType
のパラメータの有効なインデックスでない要素が含まれている場合、またはtarget.type()
とnewType
の対応する2つのパラメータの型が同一でない場合
-
constant
public static MethodHandle constant(Class<?> type, Object value) 要求された戻り値の型を持ち、呼び出されるたびに指定された定数値を返すメソッド・ハンドルを生成します。メソッド・ハンドルが返される前に、渡された値が要求された型に変換されます。 要求された型がプリミティブの場合はプリミティブ・ワイドニング変換が試みられ、それ以外の場合は参照変換が試みられます。
返されるメソッド・ハンドルは
identity(type).bindTo(value)
と同等です。- パラメータ:
type
- 必要なメソッド・ハンドルの戻り値の型value
- 返す値- 戻り値:
- 指定された戻り値の型を持ち引数は一切取らない、常に指定された値を返すメソッド・ハンドル
- 例外:
NullPointerException
-type
引数がnullの場合ClassCastException
- 要求された戻り値の型に値を変換できない場合IllegalArgumentException
- 指定された型がvoid.class
の場合
-
identity
public static MethodHandle identity(Class<?> type) 呼出し時に唯一の引数の値を返すメソッド・ハンドルを生成します。- パラメータ:
type
- 必要なメソッド・ハンドルの唯一のパラメータと戻り値の型- 戻り値:
- 指定された型を受け入れて返す単項メソッド・ハンドル
- 例外:
NullPointerException
- 引数がnullの場合IllegalArgumentException
- 指定された型がvoid.class
の場合
-
zero
public static MethodHandle zero(Class<?> type) リクエストされた戻り型の定数メソッド・ハンドルを生成します。このハンドルは、呼び出されるたびにその型のデフォルト値を返します。 結果の定数メソッド・ハンドルには副作用はありません。返されるメソッド・ハンドルは、
empty(methodType(type))
と等価です。 また、explicitCastArguments
はnull
をデフォルト値に変換するため、explicitCastArguments(constant(Object.class, null), methodType(type))
と同等です。- パラメータ:
type
- 目的のメソッド・ハンドルの期待される戻り値の型- 戻り値:
- 引数をとらず、指定された型のデフォルト値を返す定数メソッド・ハンドル(型がvoidの場合はvoid)
- 例外:
NullPointerException
- 引数がnullの場合- 導入されたバージョン:
- 9
- 関連項目:
-
empty
public static MethodHandle empty(MethodType type) リクエストされた型のメソッド・ハンドルを生成します。引数は無視され、何も実行されず、戻り値の型に応じて適切なデフォルトが返されます。 つまり、ゼロのプリミティブ値、null
またはvoid
を返します。返されるメソッド・ハンドルは、
dropArguments(zero(type.returnType()), 0, type.parameterList())
と等価です。- APIのノート:
- 述語とターゲットを指定すると、有用な"if-then"構成を
guardWithTest(pred, target, empty(target.type())
として作成できます。 - パラメータ:
type
- 目的のメソッド・ハンドルの型- 戻り値:
- 指定された型の定数メソッド・ハンドル。指定された戻り型のデフォルト値を返します
- 例外:
NullPointerException
- 引数がnullの場合- 導入されたバージョン:
- 9
- 関連項目:
-
insertArguments
public static MethodHandle insertArguments(MethodHandle target, int pos, Object... values) ターゲット・メソッド・ハンドルの呼出しの前に、1つ以上のバインド引数をメソッド・ハンドルに提供します。 ターゲットの仮パラメータのうちで、バインド引数に対応しているものは、バインド・パラメータと呼ばれます。 バインド引数を保存した新しいメソッド・ハンドルを返します。 これは呼出し時に、すべての非バインド・パラメータに対する引数を受け取り、保存しておいた引数を対応するパラメータにバインドし、元のターゲットを呼び出します。新しいメソッド・ハンドルの型には、元のターゲットの型に含まれていたバインド・パラメータの型は含まれませんが、これは、新しいメソッド・ハンドルではもう、呼出し元がそれらの引数を指定する必要がないからです。
指定された引数のオブジェクトはそれぞれ、対応するバインド・パラメータの型に一致する必要があります。 バインド・パラメータの型がプリミティブの場合、引数のオブジェクトはラッパーである必要があり、オブジェクトがアンボクシングされてプリミティブ値が生成されます。
pos
引数によってバインドするパラメータが選択されます。 その範囲は0 - N-L (両端を含む)です。ここで、Nはターゲット・メソッド・ハンドルの引数長、Lは値配列の長さです。ノート: 元のターゲット・メソッド・ハンドルであっても、結果のアダプタは決して可変メソッド・ハンドルではありません。
- パラメータ:
target
- 引数を挿入したあとに呼び出すメソッド・ハンドルpos
- 引数の挿入位置(先頭の場合はゼロ)values
- 挿入する一連の引数- 戻り値:
- 追加の引数を挿入してから元のメソッド・ハンドルを呼び出すメソッド・ハンドル
- 例外:
NullPointerException
- ターゲットまたはvalues
配列がnullの場合IllegalArgumentException
-pos
が0
より小さいか、N - L
より大きい場合、N
はターゲット・メソッド・ハンドルのアリティ、L
は値配列の長さです。ClassCastException
- 引数が対応するバウンド・パラメータ・タイプと一致しない場合。- 関連項目:
-
dropArguments
public static MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) いくつかのダミー引数を破棄してから指定された別のtargetメソッド・ハンドルを呼び出すメソッド・ハンドルを生成します。 新しいメソッド・ハンドルの型は、ターゲットの型とほぼ同じになりますが、指定された位置にダミー引数の型も含む点が異なります。pos
引数の範囲は0 - N (Nはターゲットの引数の数)になります。 ダミー引数は、pos
が0の場合はターゲットの実際の引数の前に追加され、pos
がNの場合は後ろに追加されます。例:
import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodType.*; ... MethodHandle cat = lookup().findVirtual(String.class, "concat", methodType(String.class, String.class)); assertEquals("xy", (String) cat.invokeExact("x", "y")); MethodType bigType = cat.type().insertParameterTypes(0, int.class, String.class); MethodHandle d0 = dropArguments(cat, 0, bigType.parameterList().subList(0,2)); assertEquals(bigType, d0.type()); assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
このメソッドは次のコードとも同等です。
dropArguments
(target, pos, valueTypes.toArray(new Class[0]))
- パラメータ:
target
- 引数を除去したあとに呼び出すメソッド・ハンドルpos
- 除去する最初の引数の位置(左端の場合は0)valueTypes
- 除去する引数の型- 戻り値:
- 指定された型の引数を除去してから元のメソッド・ハンドルを呼び出すメソッド・ハンドル
- 例外:
NullPointerException
- ターゲットがnullの場合、またはvalueTypes
リストまたはそのいずれかの要素がnullの場合IllegalArgumentException
-valueTypes
のいずれかの要素がvoid.class
の場合、またはpos
が負であるかターゲットの引数の数より大きい場合、または新しいメソッド・ハンドルの型に含まれるパラメータの数が多すぎる場合
-
dropArguments
public static MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) いくつかのダミー引数を破棄してから指定された別のtargetメソッド・ハンドルを呼び出すメソッド・ハンドルを生成します。 新しいメソッド・ハンドルの型は、ターゲットの型とほぼ同じになりますが、指定された位置にダミー引数の型も含む点が異なります。pos
引数の範囲は0 - N (Nはターゲットの引数の数)になります。 ダミー引数は、pos
が0の場合はターゲットの実際の引数の前に追加され、pos
がNの場合は後ろに追加されます。- APIのノート:
-
import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodType.*; ... MethodHandle cat = lookup().findVirtual(String.class, "concat", methodType(String.class, String.class)); assertEquals("xy", (String) cat.invokeExact("x", "y")); MethodHandle d0 = dropArguments(cat, 0, String.class); assertEquals("yz", (String) d0.invokeExact("x", "y", "z")); MethodHandle d1 = dropArguments(cat, 1, String.class); assertEquals("xz", (String) d1.invokeExact("x", "y", "z")); MethodHandle d2 = dropArguments(cat, 2, String.class); assertEquals("xy", (String) d2.invokeExact("x", "y", "z")); MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class); assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
このメソッドは次のコードとも同等です。
dropArguments
(target, pos, Arrays.asList(valueTypes))
- パラメータ:
target
- 引数を除去したあとに呼び出すメソッド・ハンドルpos
- 除去する最初の引数の位置(左端の場合は0)valueTypes
- 除去する引数の型- 戻り値:
- 指定された型の引数を除去してから元のメソッド・ハンドルを呼び出すメソッド・ハンドル
- 例外:
NullPointerException
- ターゲットがnullの場合、またはvalueTypes
配列またはそのいずれかの要素がnullの場合IllegalArgumentException
-valueTypes
のいずれかの要素がvoid.class
の場合、またはpos
が負またはターゲットの引数カウントより大きい場合、または新しいメソッド・ハンドルの型のパラメータ数が多すぎる場合
-
dropArgumentsToMatch
public static MethodHandle dropArgumentsToMatch(MethodHandle target, int skip, List<Class<?>> newTypes, int pos) 指定されたパラメータ・タイプ・リストと一致するようにターゲット・メソッド・ハンドルを適応させます。 必要に応じて、ダミーの引数を追加します。 一部の先行パラメータは、照合の開始前にスキップできます。target
のパラメータ・タイプ・リストの残りのタイプは、開始位置pos
にあるnewTypes
タイプ・リストのサブリストである必要があります。 結果のハンドルには、ターゲット・ハンドルのパラメータ・タイプ・リストがあり、一致しないパラメータ・タイプ(一致するサブリストの前後に)が、dropArguments(MethodHandle, int, Class[])
のように、ターゲットの元のパラメータの対応する位置に挿入されます。結果のハンドルは、ターゲット・ハンドルと同じ戻り型になります。
より正式な用語では、次の2つのタイプ・リストを想定します:
- ターゲット・ハンドルは、
skip
で示されるように、S
に多くの型を持つパラメータ型リストS..., M...
を持っています。M
型は、指定された型リストnewTypes
の一部と一致すると想定される型です。 newTypes
リストには、pos
で示されるように、P
に多くの型が含まれるP..., M..., A...
型が含まれています。M
型は、ターゲット・ハンドルのパラメータ・タイプ・リストのM
型が一致すると想定される型です。A
内の型は、一致するサブリストの後に検出される追加の型です。
dropArgumentsToMatch
の呼出しの結果は、パラメータ・タイプ・リストS..., P..., M..., A...
を持ち、P
およびA
型はdropArguments(MethodHandle, int, Class[])
のように挿入されます。- APIのノート:
- 引数リストが"効果的に同一" (つまり、共通プレフィクス内で同一です)である2つのメソッド・ハンドルは、次のように、
dropArgumentsToMatch
への2回の呼び出しによって共通の型に相互変換できます:import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodType.*; ... ... MethodHandle h0 = constant(boolean.class, true); MethodHandle h1 = lookup().findVirtual(String.class, "concat", methodType(String.class, String.class)); MethodType bigType = h1.type().insertParameterTypes(1, String.class, int.class); MethodHandle h2 = dropArguments(h1, 0, bigType.parameterList()); if (h1.type().parameterCount() < h2.type().parameterCount()) h1 = dropArgumentsToMatch(h1, 0, h2.type().parameterList(), 0); // lengthen h1 else h2 = dropArgumentsToMatch(h2, 0, h1.type().parameterList(), 0); // lengthen h2 MethodHandle h3 = guardWithTest(h0, h1, h2); assertEquals("xy", h3.invoke("x", "y", 1, "a", "b", "c"));
- パラメータ:
target
- 適応するメソッド・ハンドルskip
- (それらは変わらないでしょう)を無視するターゲット・パラメータの数newTypes
-target
のパラメータ・タイプ・リストと一致する型のリストpos
- スキップされていないターゲット・パラメータが発生しなければならないnewTypes
に配置- 戻り値:
- 場合によっては適合したメソッド・ハンドル
- 例外:
NullPointerException
- どちらかの引数がnullの場合IllegalArgumentException
-newTypes
のいずれかの要素がvoid.class
である場合、またはskip
が負であるかターゲットのアリティより大きい場合、またはpos
が負であるかnewTypesリスト・サイズより大きい場合、またはnewTypes
が位置pos
でtarget
の非スキップ・パラメータ・タイプを含まない場合。- 導入されたバージョン:
- 9
- ターゲット・ハンドルは、
-
dropReturn
public static MethodHandle dropReturn(MethodHandle target) ターゲット・ハンドル(もしあれば)の戻り値を削除します。 返されるメソッド・ハンドルは、void
の戻り型を持ちます。- パラメータ:
target
- 適応するメソッド・ハンドル- 戻り値:
- 場合によっては適合したメソッド・ハンドル
- 例外:
NullPointerException
-target
がnullである場合- 導入されたバージョン:
- 16
-
filterArguments
public static MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) ターゲット・メソッド・ハンドルを適応させるため、その1つ以上の引数をそれぞれ固有の単項フィルタ関数を使って前処理したあと、前処理を行った各引数を対応するフィルタ関数の結果で置き換えてターゲットを呼び出します。前処理は、
filters
配列の要素として指定された1つ以上のメソッド・ハンドルによって実行されます。 フィルタ配列の最初の要素がターゲットのpos
の位置の引数に対応する、といった関係がその後も順に続きます。 フィルタ関数は、左から右の順序で起動されます。配列内のnull引数はアイデンティティ関数とみなされ、対応する引数は変更されないままになります。 (nullでない要素が配列内に1つも存在しない場合は、元のターゲットが返されます。) 各フィルタはアダプタの対応する引数に適用されます。
フィルタ
F
がターゲットのN
番目の引数に適用される場合、F
は、ちょうど1つの引数を取るメソッド・ハンドルでなければいけません。 結果となる適応後のメソッド・ハンドル内では、F
の唯一の引数の型で、ターゲットの対応する引数の型が置き換えられます。F
の戻り値の型は、ターゲットの対応するパラメータの型と同一でなければいけません。ターゲット内の引数位置に対応しない
filters
の要素(nullの場合がある)が存在する場合は、エラーになります。例:
import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodType.*; ... MethodHandle cat = lookup().findVirtual(String.class, "concat", methodType(String.class, String.class)); MethodHandle upcase = lookup().findVirtual(String.class, "toUpperCase", methodType(String.class)); assertEquals("xy", (String) cat.invokeExact("x", "y")); MethodHandle f0 = filterArguments(cat, 0, upcase); assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy MethodHandle f1 = filterArguments(cat, 1, upcase); assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY MethodHandle f2 = filterArguments(cat, 0, upcase, upcase); assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
次に、結果のアダプタの疑似コードを示します。 コードで、
T
は、target
と結果のアダプタの両方の戻り型を示します。P
/p
およびB
/b
は、フィルタ位置pos
の前後にそれぞれ存在するパラメータおよび引数の型と値を表します。A[i]
/a[i]
は、フィルタされたパラメータおよび引数の型と値を表し、filter[i]
ハンドルの戻り型も表します。 後者は、V[i]
型の引数v[i]
を受け入れます。これは、結果のアダプタのシグネチャにも表示されます。T target(P... p, A[i]... a[i], B... b); A[i] filter[i](V[i]); T adapter(P... p, V[i]... v[i], B... b) { return target(p..., filter[i](v[i])..., b...); }
ノート: 元のターゲット・メソッド・ハンドルであっても、結果のアダプタは決して可変メソッド・ハンドルではありません。
- パラメータ:
target
- 引数をフィルタリングしたあとで呼び出すメソッド・ハンドルpos
- フィルタリングする最初の引数の位置filters
- フィルタリング対象の引数に対して最初に呼び出すメソッド・ハンドル- 戻り値:
- 指定された引数フィルタリング・ロジックが組み込まれたメソッド・ハンドル
- 例外:
NullPointerException
- ターゲットがnullの場合またはfilters
配列がnullの場合IllegalArgumentException
-filters
の非null要素がターゲットの対応する引数型と一致しない場合(前述の説明を参照)、またはpos+filters.length
がtarget.type().parameterCount()
より大きい場合、または結果のメソッド・ハンドルの型のパラメータ数が多すぎる場合
-
collectArguments
public static MethodHandle collectArguments(MethodHandle target, int pos, MethodHandle filter) ターゲット・メソッド・ハンドルを、フィルタ(別のメソッド・ハンドル)でその引数のサブシーケンスを前処理することにより、適応させます。 前処理した引数は、フィルタ関数の結果(ある場合)によって置き換えられます。 すると、ターゲットは変更された(通常は短縮された)引数リストで呼び出されます。フィルタが値を返す場合、ターゲットはその値を位置
pos
(フィルタに渡されない引数の前または後)の引数として受け入れる必要があります。 フィルタがvoidを返す場合、ターゲットはフィルタに渡されないすべての引数を受け入れる必要があります。 引数は並べ替えられず、フィルタから返された結果によってアダプタにもともと渡された引数サブシーケンス全体が(順番に)置き換えられます。フィルタの引数型(ある場合)は、結果の適応済メソッド・ハンドル内で、ターゲットの0または1個の引数型(位置
pos
)を置き換えます。 フィルタの戻り型(ある場合)は、ターゲットの位置pos
の引数型と同じである必要があり、そのターゲット引数はフィルタの戻り値によって提供されます。どのような場合でも、
pos
は0以上である必要があり、pos
はターゲットの引数カウント以下である必要があります。例:
import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodType.*; ... MethodHandle deepToString = publicLookup() .findStatic(Arrays.class, "deepToString", methodType(String.class, Object[].class)); MethodHandle ts1 = deepToString.asCollector(String[].class, 1); assertEquals("[strange]", (String) ts1.invokeExact("strange")); MethodHandle ts2 = deepToString.asCollector(String[].class, 2); assertEquals("[up, down]", (String) ts2.invokeExact("up", "down")); MethodHandle ts3 = deepToString.asCollector(String[].class, 3); MethodHandle ts3_ts2 = collectArguments(ts3, 1, ts2); assertEquals("[top, [up, down], strange]", (String) ts3_ts2.invokeExact("top", "up", "down", "strange")); MethodHandle ts3_ts2_ts1 = collectArguments(ts3_ts2, 3, ts1); assertEquals("[top, [up, down], [strange]]", (String) ts3_ts2_ts1.invokeExact("top", "up", "down", "strange")); MethodHandle ts3_ts2_ts3 = collectArguments(ts3_ts2, 1, ts3); assertEquals("[top, [[up, down, strange], charm], bottom]", (String) ts3_ts2_ts3.invokeExact("top", "up", "down", "strange", "charm", "bottom"));
次に、結果のアダプタの疑似コードを示します。 コードで、
T
は、target
および結果のアダプタの戻り型を表します。V
/v
は、V
がvoid
でないかぎり、target
のシグネチャおよび引数にもそれぞれ存在するfilter
の戻り型および値の表記です。A
/a
およびC
/c
は、target
のシグネチャの収集位置pos
の前後のパラメータ・タイプおよび値を表します。 また、結果のアダプタのシグネチャと引数も表示されます。ここでは、filter
(もしあれば)に対するパラメータ・タイプと引数を表すB
/b
を囲みます。T target(A...,V,C...); V filter(B...); T adapter(A... a,B... b,C... c) { V v = filter(b...); return target(a...,v,c...); } // and if the filter has no arguments: T target2(A...,V,C...); V filter2(); T adapter2(A... a,C... c) { V v = filter2(); return target2(a...,v,c...); } // and if the filter has a void return: T target3(A...,C...); void filter3(B...); T adapter3(A... a,B... b,C... c) { filter3(b...); return target3(a...,c...); }
コレクション・アダプタ
collectArguments(mh, 0, coll)
は、次のような個別のステップで、まず影響を受ける引数を折りたたんでから(fold)破棄(drop)するものと同等です。mh = MethodHandles.dropArguments(mh, 1, coll.type().parameterList()); //step 2 mh = MethodHandles.foldArguments(mh, coll); //step 1
coll
の結果(ある場合)以外に引数を消費しない場合は、collectArguments(mh, 0, coll)
はfilterReturnValue(coll, mh)
と同等です。 フィルタ・メソッド・ハンドルcoll
が1つの引数を消費して非void結果を生成する場合は、collectArguments(mh, N, coll)
はfilterArguments(mh, N, coll)
と同等です。 他の等価性も可能ですが、引数順列が必要です。ノート: 元のターゲット・メソッド・ハンドルであっても、結果のアダプタは決して可変メソッド・ハンドルではありません。
- パラメータ:
target
- 引数サブシーケンスをフィルタした後に呼び出すメソッド・ハンドルpos
- フィルタに渡す最初のアダプタ引数、またはフィルタの結果を受け取るターゲット引数、あるいはその両方の位置filter
- 引数サブシーケンスで呼び出すメソッド・ハンドル- 戻り値:
- 指定された引数サブシーケンス・フィルタリング・ロジックを組み込んだメソッド・ハンドル
- 例外:
NullPointerException
- どちらかの引数がnullの場合IllegalArgumentException
-filter
の戻り型が非voidでターゲットのpos
引数と同じでない場合、またはpos
が0からターゲットの引数カウントの間(含む)にない場合、または結果のメソッド・ハンドルの型のパラメータ数が多すぎる場合- 関連項目:
-
filterReturnValue
public static MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) ターゲット・メソッド・ハンドルを適応させるため、その戻り値(存在する場合)をフィルタ(別のメソッド・ハンドル)で後処理します。 フィルタの結果がアダプタから返されます。ターゲットが値を返す場合、フィルタはその値を唯一の引数として受け入れる必要があります。 ターゲットがvoidを返す場合、フィルタは引数を一切受け入れてはいけません。
結果となる適応後のメソッド・ハンドル内では、フィルタの戻り値の型でターゲットの戻り値の型が置き換えられます。 フィルタの引数の型(存在する場合)は、ターゲットの戻り値の型と同一でなければいけません。
例:
import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodType.*; ... MethodHandle cat = lookup().findVirtual(String.class, "concat", methodType(String.class, String.class)); MethodHandle length = lookup().findVirtual(String.class, "length", methodType(int.class)); System.out.println((String) cat.invokeExact("x", "y")); // xy MethodHandle f0 = filterReturnValue(cat, length); System.out.println((int) f0.invokeExact("x", "y")); // 2
次に、結果のアダプタの疑似コードを示します。 コードでは、
T
/t
は、target
の結果タイプと値、V
、filter
の結果タイプ、およびA
/a
、target
のパラメータと引数の型と値、および結果のアダプタを表します。T target(A...); V filter(T); V adapter(A... a) { T t = target(a...); return filter(t); } // and if the target has a void return: void target2(A...); V filter2(); V adapter2(A... a) { target2(a...); return filter2(); } // and if the filter has a void return: T target3(A...); void filter3(V); void adapter3(A... a) { T t = target3(a...); filter3(t); }
ノート: 元のターゲット・メソッド・ハンドルであっても、結果のアダプタは決して可変メソッド・ハンドルではありません。
- パラメータ:
target
- 戻り値をフィルタリングする前に呼び出すメソッド・ハンドルfilter
- 戻り値に対して呼び出すメソッド・ハンドル- 戻り値:
- 指定された戻り値フィルタリング・ロジックが組み込まれたメソッド・ハンドル
- 例外:
NullPointerException
- どちらかの引数がnullの場合IllegalArgumentException
- 前述のようにfilter
の引数リストがターゲットの戻り値の型と一致しない場合
-
foldArguments
public static MethodHandle foldArguments(MethodHandle target, MethodHandle combiner) ターゲット・メソッド・ハンドルを適応させるため、その引数のいくつかを前処理したあと、前処理の結果を元の一連の引数内に挿入してターゲットを呼び出します。前処理は、2番目のメソッド・ハンドルである
combiner
によって実行されます。 アダプタに渡された引数のうち、最初のN
個の引数がコンバイナにコピーされたあと、コンバイナが呼び出されます。 (ここで、N
はコンバイナのパラメータ数として定義される。) このあと制御がターゲットに渡されますが、その際、コンバイナのすべての結果が元のN
個の入力引数の前に挿入されます。コンバイナが値を返す場合、ターゲットの最初のパラメータの型がコンバイナの戻り値の型と同一である必要があるほか、ターゲットの次の
N
個のパラメータの型がコンバイナのパラメータと厳密に一致している必要があります。コンバイナの戻り値がvoidの場合、結果は一切挿入されないので、ターゲットの最初の
N
個のパラメータの型がコンバイナのパラメータと厳密に一致する必要があります。結果となるアダプタの型はターゲットとほぼ同じになりますが、最初のパラメータの型がコンバイナの結果に対応している場合はその型は除去される点が異なります。
(
dropArguments
を使えば、コンバイナまたはターゲットが受け取る必要のない引数をすべて削除できます。 入力引数の一部がコンバイナ専用の場合、それらの引数はターゲットへのエントリ時にスタック上に存在している必要がないため、asCollector
を代わりに使用することを検討してください。)例:
import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodType.*; ... MethodHandle trace = publicLookup().findVirtual(java.io.PrintStream.class, "println", methodType(void.class, String.class)) .bindTo(System.out); MethodHandle cat = lookup().findVirtual(String.class, "concat", methodType(String.class, String.class)); assertEquals("boojum", (String) cat.invokeExact("boo", "jum")); MethodHandle catTrace = foldArguments(cat, trace); // also prints "boo": assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
次に、結果のアダプタの疑似コードを示します。 コードで、
T
は、target
の結果タイプと結果のアダプタを表します。V
/v
は、折り返し位置に先行するtarget
のパラメータと引数の型と値を表します。V
もcombiner
の結果型です。A
/a
は、N
パラメータおよび引数の型と値を折りたたみ位置で示します。B
/b
は、target
パラメータおよび引数の型と値を表し、折り返されたパラメータおよび引数の後に続きます。// there are N arguments in A... T target(V, A[N]..., B...); V combiner(A...); T adapter(A... a, B... b) { V v = combiner(a...); return target(v, a..., b...); } // and if the combiner has a void return: T target2(A[N]..., B...); void combiner2(A...); T adapter2(A... a, B... b) { combiner2(a...); return target2(a..., b...); }
ノート: 元のターゲット・メソッド・ハンドルであっても、結果のアダプタは決して可変メソッド・ハンドルではありません。
- パラメータ:
target
- 引数を結合したあとで呼び出すメソッド・ハンドルcombiner
- 入力引数に対して最初に呼び出すメソッド・ハンドル- 戻り値:
- 指定された引数フォールディング・ロジックが組み込まれたメソッド・ハンドル
- 例外:
NullPointerException
- どちらかの引数がnullの場合IllegalArgumentException
-combiner
の戻り値の型がvoidでなく、ターゲットの最初の引数の型と同じでない場合、あるいはターゲットの最初のN
個の引数の型(combiner
の戻り値の型に一致する型は除く)がcombiner
の引数の型と同一でない場合
-
foldArguments
public static MethodHandle foldArguments(MethodHandle target, int pos, MethodHandle combiner) ターゲット・メソッド・ハンドルは、指定された位置から始めて、その引数の一部を前処理し、前処理の結果でターゲットをコールして、折り畳まれた引数の直前に元の引数のシーケンスに挿入することによって適応されます。このメソッドは
foldArguments(MethodHandle, MethodHandle)
と密接に関連していますが、折り返しを行うパラメータ・リスト内の位置を制御できます。 これを制御する引数pos
は、ゼロ・ベースの索引です。 前述のメソッドfoldArguments(MethodHandle, MethodHandle)
は位置0を取ります。- APIのノート:
- 例:
import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodType.*; ... MethodHandle trace = publicLookup().findVirtual(java.io.PrintStream.class, "println", methodType(void.class, String.class)) .bindTo(System.out); MethodHandle cat = lookup().findVirtual(String.class, "concat", methodType(String.class, String.class)); assertEquals("boojum", (String) cat.invokeExact("boo", "jum")); MethodHandle catTrace = foldArguments(cat, 1, trace); // also prints "jum": assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
次に、結果のアダプタの疑似コードを示します。 コードで、
T
は、target
の結果タイプと結果のアダプタを表します。V
/v
は、折り返し位置に先行するtarget
のパラメータと引数の型と値を表します。V
もcombiner
の結果型です。A
/a
は、N
パラメータおよび引数の型と値を折りたたみ位置で示します。Z
/z
およびB
/b
は、target
パラメータと引数の型と値を表し、それぞれpos
から始まる折り畳まれたパラメータと引数の前後に配置されます。// there are N arguments in A... T target(Z..., V, A[N]..., B...); V combiner(A...); T adapter(Z... z, A... a, B... b) { V v = combiner(a...); return target(z..., v, a..., b...); } // and if the combiner has a void return: T target2(Z..., A[N]..., B...); void combiner2(A...); T adapter2(Z... z, A... a, B... b) { combiner2(a...); return target2(z..., a..., b...); }
ノート: 元のターゲット・メソッド・ハンドルであっても、結果のアダプタは決して可変メソッド・ハンドルではありません。
- パラメータ:
target
- 引数を結合したあとで呼び出すメソッド・ハンドルpos
- 折りたたみを開始し、折り畳み結果を挿入する位置。これが0
の場合、効果はfoldArguments(MethodHandle, MethodHandle)
と同じです。combiner
- 入力引数に対して最初に呼び出すメソッド・ハンドル- 戻り値:
- 指定された引数フォールディング・ロジックが組み込まれたメソッド・ハンドル
- 例外:
NullPointerException
- どちらかの引数がnullの場合IllegalArgumentException
- 以下の2つの条件のいずれかが成り立つ: (1)combiner
の戻り型は、ターゲット・シグネチャの位置pos
の引数型と同じでなく、void
以外です。(2)ターゲット・シグネチャ(combiner
の戻り型と一致する1つをスキップ)の位置pos
のN
引数型は、combiner
の引数型とは同一ではありません。- 導入されたバージョン:
- 9
- 関連項目:
-
guardWithTest
public static MethodHandle guardWithTest(MethodHandle test, MethodHandle target, MethodHandle fallback) テスト(boolean値のメソッド・ハンドル)で保護することでターゲット・メソッド・ハンドルを適応させるメソッド・ハンドルを作成します。 保護に失敗した場合は、代わりにフォール・バック・ハンドルが呼び出されます。 テストの戻り値の型がbooleanでなければいけない点と、テストの引数の数がほかの2つのメソッド・ハンドルより少なくてもかまわないという点を除き、3つのメソッド・ハンドルの対応する引数と戻り値の型はすべて同じである必要があります。次に、結果のアダプタの疑似コードを示します。 コードで、
T
は、関連する3つのハンドルの均一な結果タイプ(A
/a
、test
で使用されるtarget
パラメータおよび引数の型と値、およびB
/b
)を表します。これらの型と値は、test
では使用されないtarget
パラメータおよび引数の型と値です。boolean test(A...); T target(A...,B...); T fallback(A...,B...); T adapter(A... a,B... b) { if (test(a...)) return target(a..., b...); else return fallback(a..., b...); }
a...
)は、テストの実行時に変更される可能性はないので、呼出し元から必要に応じてターゲットまたはフォール・バックにそのまま渡されます。- パラメータ:
test
- テストに使用されるメソッド・ハンドルでbooleanを返す必要があるtarget
- テストにパスした場合に呼び出すメソッド・ハンドルfallback
- テストに失敗した場合に呼び出すメソッド・ハンドル- 戻り値:
- 指定されたif/then/elseロジックが組み込まれたメソッド・ハンドル
- 例外:
NullPointerException
- いずれかの引数がnullの場合IllegalArgumentException
-test
がbooleanを返さない場合、または(test
の戻り値の型を変更してターゲットの型と一致させても) 3つのすべてのメソッド型が一致しない場合
-
catchException
public static MethodHandle catchException(MethodHandle target, Class<? extends Throwable> exType, MethodHandle handler) ターゲットのメソッド・ハンドルを例外ハンドラの内部で実行することによって、このターゲットを適応させるメソッド・ハンドルを作成します。 ターゲットが通常どおり値を返した場合、アダプタはその値を返します。 指定された型に一致する例外がスローされた場合、代わりにその例外と元の引数を指定してフォール・バック・ハンドルが呼び出されます。ターゲットとハンドラの対応する引数と戻り値の型は基本的に同じである必要がありますが、ハンドラでは(
guardWithTest
の述語と同様に)末尾の複数の引数を省略できます。 さらにハンドラは、exType
またはスーパー・タイプの先頭のパラメータを追加で1つ持つ必要があります。次に、結果のアダプタの疑似コードを示します。 コードでは、
T
は、target
およびhandler
の戻り型を表し、それに対応する結果のアダプタの戻り型を表します。A
/a
は、handler
によって消費される結果ハンドルの引数の型と値、B
/b
は、handler
によって破棄される結果ハンドルの引数の型と値です。T target(A..., B...); T handler(ExType, A...); T adapter(A... a, B... b) { try { return target(a..., b...); } catch (ExType ex) { return handler(ex, a...); } }
a...
)は、ターゲットの実行時に変更される可能性はないので、ハンドラが呼び出される場合には呼出し元からハンドラにそのまま渡されます。ハンドラが常にスローする場合でも、ターゲットとハンドラの戻り値の型は同じでなければいけません。 (これは、たとえばハンドラが
finally
節をシミュレートしているために発生する可能性があります)。 そのようなスローするハンドラを作成するには、throwException
を使ってハンドラ作成ロジックを構築し、正しい戻り値の型を持つメソッド・ハンドルが作成されるようにします。- パラメータ:
target
- 呼び出すメソッド・ハンドルexType
- ハンドラがキャッチする例外の型handler
- 一致する例外がスローされた場合に呼び出すメソッド・ハンドル- 戻り値:
- 指定されたtry/catchロジックが組み込まれたメソッド・ハンドル
- 例外:
NullPointerException
- いずれかの引数がnullの場合IllegalArgumentException
-handler
が指定された例外の型を受け入れない場合、またはメソッド・ハンドルの型に含まれる戻り値の型と対応するパラメータが一致しない場合- 関連項目:
-
throwException
public static MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) 指定されたexType
の例外をスローするメソッド・ハンドルを生成します。 メソッド・ハンドルは、exType
の単一の引数を受け入れ、それを即時に例外としてスローします。 メソッド型では形式上、returnType
の戻り値が指定されます。 戻り値の型は、どのようなものでもかまいません。メソッド・ハンドルが通常どおりに戻ることは決してないので、メソッド・ハンドルの動作には何の影響もありません。- パラメータ:
returnType
- 期待するメソッド・ハンドルの戻り型exType
- 期待するメソッド・ハンドルのパラメータ型- 戻り値:
- 指定された例外をスローできるメソッド・ハンドル
- 例外:
NullPointerException
- どちらかの引数がnullの場合
-
loop
public static MethodHandle loop(MethodHandle[]... clauses) 反復ごとに更新およびチェックされる複数のループ変数を持つループを表すメソッド・ハンドルを構築します。 いずれかの述語が原因でループが終了すると、対応するファイナライザが実行され、結果として得られるハンドルの戻り値であるループの結果が提供されます。直感的に、すべてのループは1つ以上の"clauses"によって形成され、それぞれがローカルの「反復変数」またはループ終了(あるいはその両方)を指定します。 ループの各反復処理では、各句が順番に実行されます。 句はオプションで反復変数を更新できます。オプションで、テストおよび条件付きループの終了を実行することもできます。 メソッド・ハンドルに関してこのロジックを表現するために、各句では最大4つの独立したアクションを指定します:
- init: ループが実行される前に、
V
型の反復変数v
の初期化を行います。 - ステップ: 句が実行されると、反復変数
v
の更新ステップが実行されます。 - pred: 句が実行されると、ループ終了をテストする述語の実行。
- fini: 句によってループが終了すると、ファイナライザの実行によってループの戻り値がコンピュートされます。
(V...)
と表記されます。 値自体は(v...)
になります。 "パラメータ・リスト"については、通常、型を参照しますが、一部のコンテキストでは(実行を記述)のリストが実際の値になります。これらの句の一部を特定のルールに従って省略でき、この場合は有効なデフォルトの動作が提供されます。 詳細は、次を参照してください。
どこでもオプションのパラメータ: 各句機能は許可されていますが、各反復変数
v
のパラメータを受け入れる必要はありません。 例外として、initファンクションは、initファンクションの実行時にこれらの値がまだ計算されないため、v
パラメータを使用できません。 どの句関数でも、取得する権利があるパラメータの末尾の部分列を取得することを無視できます。 実際には、どの句関数も引数をまったく取らない場合があります。ループ・パラメータ: 句関数は、資格のあるすべての反復変数値を取得できます。この場合、後続のパラメータも取得できます。 このような余分な値は、「ループ・パラメータ」と呼ばれ、その型と値は
(A...)
と(a...)
と表記されています。 これらは、ループが実行されるたびに指定される、結果のループ・ハンドルのパラメータになります。 (init関数は反復変数v
を受け入れないので、init関数のどのパラメータも自動的にループ・パラメータa
です。) 反復変数と同様に、句関数は許可されますが、ループ・パラメータを受け入れる必要はありません。 これらのループ・パラメータは、ループ全体にわたって表示されるループ不変値として機能します。どこでも表示できるパラメータ: 各非init句関数は、現在の反復変数値および受信ループ・パラメータの完全リスト
(v... a...)
を渡すことができるため、ループ状態全体を監視できます。 init関数は、初期ループ状態を(a...)
の形式で監視できます。 ほとんどの句関数は、この情報をすべて必要としませんが、dropArguments(java.lang.invoke.MethodHandle, int, java.util.List<java.lang.Class<?>>)
のように正式にそれに接続されます。 具体的には、表記(V*)
を使用して、完全なシーケンス(V...)
((v*)
,(A*)
,(a*)
の場合も同様です)の任意のプレフィクスを表現します。 この表記法では、初期化パラメータ・パラメータ・リストの一般的な形式は(A*)
で、非initファンクション・パラメータ・リストの一般的な形式は(V*)
または(V... A*)
です。チェック句の構造: 一連の句を指定すると、ループのすべての部分を接続するために、いくつかのチェックと調整が実行されます。 これらは、次のステップで詳しく説明されています。 これらのステップでは、必要な制約がループ・コンビネータへの入力によって満たされない場合に、
IllegalArgumentException
がスローされる場所に対応する単語が出現します。効果的に同一の配列: パラメータ・リスト
A
は、A
とB
が同じ場合、またはA
が短く、B
の適切なプレフィクスと同じ場合、別のパラメータ・リストB
に対して効果的に同一として定義されます。 順序付けられていないパラメータ・リスト・セットについて言えば、セットに最長のリストが含まれ、セットのすべてのメンバーがその最長のリストと事実上同じである場合は、セットが全体として"効果的に同一"であるとします。 たとえば、(V*)
形式の型シーケンスのセットは実質的に同一であり、(V... A*)
形式のシーケンスがさらに追加された場合は同じです。ステップ0: 条項構造を決定します。
- 句配列(型
MethodHandle[][]
の)は、null
以外で、少なくとも1つの要素を含んでいる必要があります。 - 句配列には、4つの要素より長い
null
またはサブ配列を含めることはできません。 - 4つより短い句は、
null
要素によって4つの長さにパディングされたものとして処理されます。 パディングは、配列に要素を追加することによって行われます。 - すべての
null
を含む句は無視されます。 - 各句は、"init"、"step"、"pred"および"fini"と呼ばれる4つの関数のタプルとして扱われます。
ステップ1A: 繰り返し変数の型
(V...)
を決定します。- 各句の反復変数タイプは、句のinitおよびstep戻り型を使用して決定されます。
- 両方の関数を省略した場合、対応する句(
void
がその型を示すために使用されます。)の反復変数はありません。 いずれかを省略すると、もう一方の戻り型は、句の反復変数型を定義します。 両方が指定されている場合、共通の戻り型(それらは同一でなければならない)は、句の反復変数型を定義します。 void
のすべての出現を省略して、戻り値の型(in句の順)のリストを作成します。- この型のリストは、"反復変数型" (
(V...)
)と呼ばれます。
ステップ1B: ループ・パラメータ
(A...)
を決定します。- init関数のパラメータ・リスト(これらは
(A*)
の形式です)を調べて収集します。 - 反復変数タイプを削除した後、ステップ、predおよびfiniパラメータ・リストのサフィクスを調べ、収集します。 (
(V... A*)
の形式が必要です。(A*)
の部分のみを収集します。) - すべての反復変数タイプで始まらないステップ、予測およびfiniパラメータ・リストからサフィクスを収集しないでください。 (これらのタイプは、すべての条項関数タイプとともにステップ2でチェックインされます。)
- 省略された句関数は無視されます。 (同様に、空のパラメータ・リストがあるとみなされます。)
- 収集されたすべてのパラメータ・リストは事実上同一である必要があります。
- 最も長いパラメータ・リスト(必然的にユニークです)は、"外部パラメータ・リスト" (
(A...)
)と呼ばれます。 - そのようなパラメータ・リストがない場合、外部パラメータ・リストは空の順序とみなされます。
- 反復変数型とそれに続く外部パラメータ型の組み合わせリストは、"内部パラメータ・リスト"と呼ばれます。
ステップ1C: ループ戻り型を決定します。
- 省略されたfini関数は無視して、fini関数の戻り型を調べます。
- fini関数がない場合、ループの戻り型は
void
です。 - それ以外の場合、fini関数(戻り値の型は同じでなければならない)の一般的な戻り型
R
は、ループ戻り型を定義します。
ステップ1D: 他のタイプを確認します。
- 少なくとも1つの非省略予測関数が必要です。
- 省略されないすべての予測関数には、
boolean
戻り型が必要です。
ステップ2: パラメータ・リストを決定します。
- 結果のループ・ハンドルのパラメータ・リストは、外部パラメータ・リスト
(A...)
になります。 - init関数のパラメータ・リストは、外部パラメータ・リストに調整されます。 (これらのパラメータ・リストは、すでにこのリストと実質的に同じです。)
- 省略されていない非初期化の(step、pred、fini)関数のパラメータ・リストは、内部パラメータ・リスト
(V... A...)
と実質的に同じである必要があります。
ステップ3: 省略した関数を入力します。
- init関数を省略した場合は、句の反復変数型に「デフォルト値」を使用します。
- ステップ関数を省略する場合は、句の反復変数型の「アイデンティティ関数」を使用します。先行する句の
void
以外の反復変数のアイデンティティ関数パラメータの前に、削除した引数パラメータを挿入します。 (これにより、ループ変数がローカル・ループ不変変数になります。) - 事前関数を省略した場合は、定数
true
関数を使用します。 (この句に関するかぎり、ループは継続されます。 そのような場合、対応するfini関数に到達できないことに注意してください。) - fini関数を省略した場合は、ループの戻り型に「デフォルト値」を使用します。
ステップ4: 欠落しているパラメータ・タイプを入力します。
- この時点で、すべてのinit関数パラメータ・リストは、外部パラメータ・リスト
(A...)
と実質的に同じですが、一部のリストが短い場合があります。 短いパラメータ・リストを持つすべてのinit関数について、リストの末尾を埋め込みます。 - この時点で、すべての非init関数パラメータ・リストは、内部パラメータ・リスト
(V... A...)
と実質的に同じですが、一部のリストが短い場合があります。 短いパラメータ・リストを持つすべての非init関数について、リストの末尾を埋め込みます。 - 引数リストは「未使用の末尾の引数を削除」によって埋められます。
最終的な観察。
- これらのステップの後、省略された関数と引数を指定することで、すべての句が調整されました。
- すべてのinit関数には、共通のパラメータ・タイプ・リスト
(A...)
があります。これは、最終ループ・ハンドルにも含まれます。 - すべてのfini関数には、一般的な戻り型
R
があり、これも最終ループ・ハンドルです。 - すべての非初期化関数には、(non-
void
)反復変数V
の共通パラメータ・タイプ・リスト(V... A...)
があり、その後にループ・パラメータが続きます。 - init関数とstep関数の各ペアは、戻り値の型
V
で一致します。 - 各非init関数は、すべての反復変数の現在の値
(v...)
を監視できます。 - すべてのファンクションは、すべてのループ・パラメータの受信値
(a...)
を監視できます。
例。 前述のステップ1Aの結果として、
loop
コンビネータには次のプロパティがあります:N
がn = 1..N
でCn = {null, Sn, Pn}
を指定すると仮定します。- 述語ハンドル
Pn
がnull
であるか、パラメータがないとします。 (1つのPn
は、非null
でなければなりません。) - ステップ・ハンドル
Sn
が、いくつかの定数X>=N
に対して(B1..BX)Rn
のシグネチャを持つとします。 Q
がvoid以外の型Rn
の数で、(V1...VQ)
がそれらの型の順序であるとします。n = 1..min(X,Q)
のVn == Bn
でなければなりません。- パラメータ型
Vn
は、ループ・ローカル状態エレメント(V...)
として解釈されます。 - 残りのタイプ
BQ+1..BX
(Q<X
の場合)は、結果のループ・ハンドルのパラメータ・タイプ(A...)
を決定します。
(A...)
がステップ関数から導出されています。これは、ほとんどのループ計算がステップで発生する場合に自然です。 一部のループでは、計算の負荷が予測関数で最も大きくなる可能性があるため、予測関数はループ・パラメータ値を受け入れる必要がある場合があります。 複雑な終了ロジックを持つループの場合、fini関数はループ・パラメータを受け入れる必要があり、同様に、複雑なエントリ・ロジックを持つループでは、init関数に余分なパラメータが必要になることがあります。 このような理由から、これらのパラメータを決定するルールは、すべての句の部分で可能なかぎり対称です。 一般に、ループ・パラメータはループ全体で共通の不変値として機能し、反復変数は共通のバリアント値、または(ステップ機能がない場合)は内部ループ不変時間を表します。ループの実行。
- ループが呼び出されると、ループ入力値はローカルに保存され、すべての句関数に渡されます。 これらのローカルはループ不変です。
- 各init関数は句の順序(外部引数
(a...)
を渡します。)で実行され、void
以外の値は(反復変数として(v...)
)をローカルに保存されます。 これらのローカルの人々は、ループ変化(前述のように、それらのステップがアイデンティティ機能として動作しないかぎり、)になります。 - すべてのファンクション実行(init関数を除く)は、
void
以外の反復値(v...)
(in句の順)から構成される内部パラメータ・リストに渡され、ループは(a...)
(引数順に)と入力します。 - 次に、pred関数が
false
を返すまで、ステップ関数およびpred関数は句の順序(前の一歩)で実行されます。 - ステップ関数コールからの
void
以外の結果は、ループ変数のシーケンス(v...)
内の対応する値を更新するために使用されます。 更新された値は、後続のすべての関数コールですぐに表示されます。 - Pred関数が
false
を返す場合、対応するfini関数がコールされ、結果の値(型R
の)がループ全体から返されます。 - すべてのpred関数が常にtrueを返す場合、fini関数は呼び出されず、例外をスローする以外はループを終了できません。
使用上のヒント。
- 各ステップ・ファンクションは、ループ変数allの現在の値を受け取りますが、ステップ・ファンクションが独自の変数の現在の値のみを監視する必要がある場合があります。 その場合、ステップ関数で明示的に「前のすべてのループ変数を削除」が必要になることがあります。 これには、
dropArguments(step, 0, V0.class, ...)
のような式で型を記述する必要があります。 - ループ変数は、変更する必要はありません。ループ不変変数にすることができます。 句は、ステップ、プレッドまたはfini関数を含まない適切なinit関数によってループ不変式を作成できます。 これは、隣接するループ変数のステップまたは前関数への着信ループ引数を"wire"する場合に役立ちます。
- 一部の句関数がインスタンス上の仮想メソッドである場合、
new MethodHandle[]{identity(ObjType.class)}
などの初期句を使用して、インスタンス自体を初期不変ループ"variable"に簡単に配置できます。 その場合、インスタンス参照は最初の反復変数値になり、句部分として仮想メソッドを簡単に使用できます。これは、すべてのインスタンス参照がその値と一致する先行インスタンス参照を取るためです。
結果のループ・ハンドルの疑似コードを次に示します。 前述のように、
V
およびv
はループ変数の型と値を表し、A
およびa
はループ全体に渡される引数を表し、R
はすべてのファイナライザおよび結果のループの共通の結果型です。V... init...(A...); boolean pred...(V..., A...); V... step...(V..., A...); R fini...(V..., A...); R loop(A... a) { V... v... = init...(a...); for (;;) { for ((v, p, s, f) in (v..., pred..., step..., fini...)) { v = s(v..., a...); if (!p(v..., a...)) { return f(v..., a...); } } } }
(V...)
および(A...)
は、個々の句関数がそれらのすべてを省略する場合でも、その全長に展開されています。 前述のように、欠落しているパラメータは、dropArgumentsToMatch(MethodHandle, int, List, int)
のように入力されます。- APIのノート:
- 例:
// iterative implementation of the factorial function as a loop handle static int one(int k) { return 1; } static int inc(int i, int acc, int k) { return i + 1; } static int mult(int i, int acc, int k) { return i * acc; } static boolean pred(int i, int acc, int k) { return i < k; } static int fin(int i, int acc, int k) { return acc; } // assume MH_one, MH_inc, MH_mult, MH_pred, and MH_fin are handles to the above methods // null initializer for counter, should initialize to 0 MethodHandle[] counterClause = new MethodHandle[]{null, MH_inc}; MethodHandle[] accumulatorClause = new MethodHandle[]{MH_one, MH_mult, MH_pred, MH_fin}; MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause); assertEquals(120, loop.invoke(5));
// simplified implementation of the factorial function as a loop handle static int inc(int i) { return i + 1; } // drop acc, k static int mult(int i, int acc) { return i * acc; } //drop k static boolean cmp(int i, int k) { return i < k; } // assume MH_inc, MH_mult, and MH_cmp are handles to the above methods // null initializer for counter, should initialize to 0 MethodHandle MH_one = MethodHandles.constant(int.class, 1); MethodHandle MH_pred = MethodHandles.dropArguments(MH_cmp, 1, int.class); // drop acc MethodHandle MH_fin = MethodHandles.dropArguments(MethodHandles.identity(int.class), 0, int.class); // drop i MethodHandle[] counterClause = new MethodHandle[]{null, MH_inc}; MethodHandle[] accumulatorClause = new MethodHandle[]{MH_one, MH_mult, MH_pred, MH_fin}; MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause); assertEquals(720, loop.invoke(6));
// instance-based implementation of the factorial function as a loop handle static class FacLoop { final int k; FacLoop(int k) { this.k = k; } int inc(int i) { return i + 1; } int mult(int i, int acc) { return i * acc; } boolean pred(int i) { return i < k; } int fin(int i, int acc) { return acc; } } // assume MH_FacLoop is a handle to the constructor // assume MH_inc, MH_mult, MH_pred, and MH_fin are handles to the above methods // null initializer for counter, should initialize to 0 MethodHandle MH_one = MethodHandles.constant(int.class, 1); MethodHandle[] instanceClause = new MethodHandle[]{MH_FacLoop}; MethodHandle[] counterClause = new MethodHandle[]{null, MH_inc}; MethodHandle[] accumulatorClause = new MethodHandle[]{MH_one, MH_mult, MH_pred, MH_fin}; MethodHandle loop = MethodHandles.loop(instanceClause, counterClause, accumulatorClause); assertEquals(5040, loop.invoke(7));
- パラメータ:
clauses
- 前述のルールに準拠するMethodHandle
の配列(4-tuples)の配列。- 戻り値:
- 引数によって定義されたループ動作を具体化するメソッド・ハンドル。
- 例外:
IllegalArgumentException
- 上記のいずれかの制約に違反した場合。- 導入されたバージョン:
- 9
- 関連項目:
- init: ループが実行される前に、
-
whileLoop
public static MethodHandle whileLoop(MethodHandle init, MethodHandle pred, MethodHandle body) 初期化子、本文および述語からwhile
ループを構築します。 これは「汎用ループ・コンビネータ」の便利なラッパーです。pred
ハンドルはループ条件を示し、body
はその本文を示します。 このメソッドによって生成されるループは、各反復で最初に述語を評価し、次にその本文(述語がtrue
と評価された場合)を実行します。 述部がfalse
(この場合、本文は実行されません)に評価されると、ループは終了します。init
ハンドルは、追加のオプションのループ・ローカル変数の初期値を示します。 反復ごとに、このループ・ローカル変数(存在する場合)がbody
に渡され、その呼出しから返された値で更新されます。 ループ実行の結果は、追加のループ・ローカル変数(存在する場合)の最終値になります。これらの引数ハンドルには、次の規則があります:
body
ハンドルはnull
であってはなりません。その型は、(V A...)V
の形式でなければなりません。ここで、V
は非void
です。そうでなければ(A...)void
です。 (void
の場合、void
型をV
という名前に割り当て、void
型V
がパラメータ・リストから静かに削除され、(A...)V
が残ることを理解して(V A...)V
を記述します。)- 本文のパラメータ・リスト
(V A...)
は、「内部パラメータ・リスト」と呼ばれます。 他のループ部分のパラメータ・リストを制約します。 - 反復変数タイプ
V
が内部パラメータ・リストから削除されると、結果の短いリスト(A...)
が「外部パラメータ・リスト」と呼ばれます。 - 本文の戻り型
V
は、void
以外の場合、ループの追加状態変数の型を決定します。 本文は、この型の値を受け入れて返す必要があります。V
。 init
が非null
の場合、戻り型はV
でなければなりません。 そのパラメータ・リスト(いくつかの「フォーム(A*)
」の)は、外部パラメータ・リスト(A...)
に対して「効果的に同一」でなければなりません。init
がnull
の場合、ループ変数は「デフォルト値」に初期化されます。pred
ハンドルは、null
であってはなりません。 戻り型としてboolean
が必要です。 そのパラメータ・リスト(空または(V A*)
の形式のいずれか)は、内部パラメータ・リストと実質的に同じである必要があります。
結果のループ・ハンドルの結果タイプとパラメータ・シグネチャは、次のように決定されます:
- ループ・ハンドルの結果タイプは、本文の結果タイプ
V
です。 - ループ・ハンドルのパラメータ・タイプは、外部パラメータ・リストの
(A...)
型です。
結果のループ・ハンドルの疑似コードを次に示します。 コードでは、
V
/v
は、ループの結果型だけでなく、単独のループ変数の型/値を表し、A
/a
はループに渡される引数の型を表します。V init(A...); boolean pred(V, A...); V body(V, A...); V whileLoop(A... a...) { V v = init(a...); while (pred(v, a...)) { v = body(v, a...); } return v; }
- APIのノート:
- 例:
// implement the zip function for lists as a loop handle static List<String> initZip(Iterator<String> a, Iterator<String> b) { return new ArrayList<>(); } static boolean zipPred(List<String> zip, Iterator<String> a, Iterator<String> b) { return a.hasNext() && b.hasNext(); } static List<String> zipStep(List<String> zip, Iterator<String> a, Iterator<String> b) { zip.add(a.next()); zip.add(b.next()); return zip; } // assume MH_initZip, MH_zipPred, and MH_zipStep are handles to the above methods MethodHandle loop = MethodHandles.whileLoop(MH_initZip, MH_zipPred, MH_zipStep); List<String> a = Arrays.asList("a", "b", "c", "d"); List<String> b = Arrays.asList("e", "f", "g", "h"); List<String> zipped = Arrays.asList("a", "e", "b", "f", "c", "g", "d", "h"); assertEquals(zipped, (List<String>) loop.invoke(a.iterator(), b.iterator()));
MethodHandle whileLoop(MethodHandle init, MethodHandle pred, MethodHandle body) { MethodHandle fini = (body.type().returnType() == void.class ? null : identity(body.type().returnType())); MethodHandle[] checkExit = { null, null, pred, fini }, varBody = { init, body }; return loop(checkExit, varBody); }
- パラメータ:
init
- オプションのイニシャライザ。ループ変数の初期値を指定します。null
の場合があり、デフォルトの初期値を示します。 その他の制約については、上記を参照してください。pred
- ループの条件。null
にはできません。 結果の型はboolean
でなければなりません。 その他の制約については、上記を参照してください。body
- ループの本文。null
にはできません。 ループ・パラメータと結果タイプを制御します。 その他の制約については、上記を参照してください。- 戻り値:
- 引数で説明されているように、
while
ループを実装するメソッド・ハンドル。 - 例外:
IllegalArgumentException
- 引数のルールに違反している場合。NullPointerException
-pred
またはbody
がnull
の場合。- 導入されたバージョン:
- 9
- 関連項目:
-
doWhileLoop
public static MethodHandle doWhileLoop(MethodHandle init, MethodHandle body, MethodHandle pred) 初期化子、本文および述語からdo-while
ループを構築します。 これは「汎用ループ・コンビネータ」の便利なラッパーです。pred
ハンドルはループ条件を示し、body
はその本文を示します。 このメソッドによって生成されるループは、各反復で、まず本文を実行し、次に述語を評価します。 ループは、本文の実行後に述語がfalse
と評価されると終了します。init
ハンドルは、追加のオプションのループ・ローカル変数の初期値を示します。 反復ごとに、このループ・ローカル変数(存在する場合)がbody
に渡され、その呼出しから返された値で更新されます。 ループ実行の結果は、追加のループ・ローカル変数(存在する場合)の最終値になります。これらの引数ハンドルには、次の規則があります:
body
ハンドルはnull
であってはなりません。その型は、(V A...)V
の形式でなければなりません。ここで、V
は非void
です。そうでなければ(A...)void
です。 (void
の場合、void
型をV
という名前に割り当て、void
型V
がパラメータ・リストから静かに削除され、(A...)V
が残ることを理解して(V A...)V
を記述します。)- 本文のパラメータ・リスト
(V A...)
は、「内部パラメータ・リスト」と呼ばれます。 他のループ部分のパラメータ・リストを制約します。 - 反復変数タイプ
V
が内部パラメータ・リストから削除されると、結果の短いリスト(A...)
が「外部パラメータ・リスト」と呼ばれます。 - 本文の戻り型
V
は、void
以外の場合、ループの追加状態変数の型を決定します。 本文は、この型の値を受け入れて返す必要があります。V
。 init
が非null
の場合、戻り型はV
でなければなりません。 そのパラメータ・リスト(いくつかの「フォーム(A*)
」の)は、外部パラメータ・リスト(A...)
に対して「効果的に同一」でなければなりません。init
がnull
の場合、ループ変数は「デフォルト値」に初期化されます。pred
ハンドルは、null
であってはなりません。 戻り型としてboolean
が必要です。 そのパラメータ・リスト(空または(V A*)
の形式のいずれか)は、内部パラメータ・リストと実質的に同じである必要があります。
結果のループ・ハンドルの結果タイプとパラメータ・シグネチャは、次のように決定されます:
- ループ・ハンドルの結果タイプは、本文の結果タイプ
V
です。 - ループ・ハンドルのパラメータ・タイプは、外部パラメータ・リストの
(A...)
型です。
結果のループ・ハンドルの疑似コードを次に示します。 コードでは、
V
/v
は、ループの結果型だけでなく、単独のループ変数の型/値を表し、A
/a
はループに渡される引数の型を表します。V init(A...); boolean pred(V, A...); V body(V, A...); V doWhileLoop(A... a...) { V v = init(a...); do { v = body(v, a...); } while (pred(v, a...)); return v; }
- APIのノート:
- 例:
// int i = 0; while (i < limit) { ++i; } return i; => limit static int zero(int limit) { return 0; } static int step(int i, int limit) { return i + 1; } static boolean pred(int i, int limit) { return i < limit; } // assume MH_zero, MH_step, and MH_pred are handles to the above methods MethodHandle loop = MethodHandles.doWhileLoop(MH_zero, MH_step, MH_pred); assertEquals(23, loop.invoke(23));
MethodHandle doWhileLoop(MethodHandle init, MethodHandle body, MethodHandle pred) { MethodHandle fini = (body.type().returnType() == void.class ? null : identity(body.type().returnType())); MethodHandle[] clause = { init, body, pred, fini }; return loop(clause); }
- パラメータ:
init
- オプションのイニシャライザ。ループ変数の初期値を指定します。null
の場合があり、デフォルトの初期値を示します。 その他の制約については、上記を参照してください。body
- ループの本文。null
にはできません。 ループ・パラメータと結果タイプを制御します。 その他の制約については、上記を参照してください。pred
- ループの条件。null
にはできません。 結果の型はboolean
でなければなりません。 その他の制約については、上記を参照してください。- 戻り値:
- 引数で説明されているように、
while
ループを実装するメソッド・ハンドル。 - 例外:
IllegalArgumentException
- 引数のルールに違反している場合。NullPointerException
-pred
またはbody
がnull
の場合。- 導入されたバージョン:
- 9
- 関連項目:
-
countedLoop
public static MethodHandle countedLoop(MethodHandle iterations, MethodHandle init, MethodHandle body) 指定された数の反復を実行するループを構築します。 これは「汎用ループ・コンビネータ」の便利なラッパーです。反復数は、
iterations
ハンドルの評価結果によって決まります。 ループ・カウンタi
は、型int
の余分なループ反復変数です。 これは0に初期化され、反復ごとに1ずつ増分されます。body
ハンドルがvoid
型以外のV
を返す場合、その型の先行ループ反復変数も存在します。 この変数は、オプションのinit
ハンドルを使用して、またはV
タイプの「デフォルト値」(ハンドルがnull
の場合)に初期化されます。各反復では、反復変数が
body
ハンドルの呼出しに渡されます。 本文(型V
の)から返されたvoid
以外の値は、先頭の反復変数を更新します。 ループ・ハンドル実行の結果は、その変数(V
変数がない場合はvoid
)の最後のV
値になります。引き数ハンドルには次の規則があります:
iterations
ハンドルは、null
ではなく、int
型を戻す必要があります。ここでは、パラメータ型リストでI
と呼びます。body
ハンドルはnull
であってはなりません。その型は、(V I A...)V
の形式でなければなりません。ここで、V
は非void
です。そうでなければ(I A...)void
です。 (void
の場合、void
型をV
という名前に割り当て、void
型V
がパラメータ・リストから静かに削除され、(I A...)V
が残ることを理解して(V I A...)V
を記述します。)- 本文のパラメータ・リスト
(V I A...)
は、「内部パラメータ・リスト」と呼ばれる型のリストに寄与します。 他のループ部分のパラメータ・リストを制約します。 - 特殊なケースとして、本文が
V
型およびI
型のみを提供し、追加のA
型がない場合、内部パラメータ・リストは、iterations
ハンドルの引数型A...
によって拡張されます。 - 反復変数タイプ
(V I)
が内部パラメータ・リストから削除されると、結果の短いリスト(A...)
が「外部パラメータ・リスト」と呼ばれます。 - 本文の戻り型
V
は、void
以外の場合、ループの追加状態変数の型を決定します。 本文は先行するパラメータを受け入れ、この型の値V
を戻す必要があります。 init
が非null
の場合、戻り型はV
でなければなりません。 そのパラメータ・リスト(いくつかの「フォーム(A*)
」の)は、外部パラメータ・リスト(A...)
に対して「効果的に同一」でなければなりません。init
がnull
の場合、ループ変数は「デフォルト値」に初期化されます。iterations
(いくつかの形式の(A*)
)のパラメータ・リストは、外部パラメータ・リスト(A...)
と実質的に同一でなければなりません。
結果のループ・ハンドルの結果タイプとパラメータ・シグネチャは、次のように決定されます:
- ループ・ハンドルの結果タイプは、本文の結果タイプ
V
です。 - ループ・ハンドルのパラメータ・タイプは、外部パラメータ・リストの
(A...)
型です。
結果のループ・ハンドルの疑似コードを次に示します。 コードでは、
V
/v
は2番目のループ変数の型/値およびループの結果型を表し、A...
/a...
はループに渡される引数を表します。int iterations(A...); V init(A...); V body(V, int, A...); V countedLoop(A... a...) { int end = iterations(a...); V v = init(a...); for (int i = 0; i < end; ++i) { v = body(v, i, a...); } return v; }
- APIのノート:
- 完全に適合する本文メソッドの例:
// String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s; // => a variation on a well known theme static String step(String v, int counter, String init) { return "na " + v; } // assume MH_step is a handle to the method above MethodHandle fit13 = MethodHandles.constant(int.class, 13); MethodHandle start = MethodHandles.identity(String.class); MethodHandle loop = MethodHandles.countedLoop(fit13, start, MH_step); assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("Lambdaman!"));
// String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s; // => a variation on a well known theme static String step(String v, int counter ) { return "na " + v; } // assume MH_step is a handle to the method above MethodHandle count = MethodHandles.dropArguments(MethodHandles.identity(int.class), 1, String.class); MethodHandle start = MethodHandles.dropArguments(MethodHandles.identity(String.class), 0, int.class); MethodHandle loop = MethodHandles.countedLoop(count, start, MH_step); // (v, i) -> "na " + v assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke(13, "Lambdaman!"));
// String s = "Lambdaman!", t = "na"; for (int i = 0; i < 13; ++i) { s = t + " " + s; } return s; // => a variation on a well known theme static String step(String v, int counter, int iterations_, String pre, String start_) { return pre + " " + v; } // assume MH_step is a handle to the method above MethodHandle count = MethodHandles.identity(int.class); MethodHandle start = MethodHandles.dropArguments(MethodHandles.identity(String.class), 0, int.class, String.class); MethodHandle loop = MethodHandles.countedLoop(count, start, MH_step); // (v, i, _, pre, _) -> pre + " " + v assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke(13, "na", "Lambdaman!"));
dropArgumentsToMatch(MethodHandle, int, List, int)
の使用例を示す例:// String s = "Lambdaman!", t = "na"; for (int i = 0; i < 13; ++i) { s = t + " " + s; } return s; // => a variation on a well known theme static String step(String v, int counter, String pre) { return pre + " " + v; } // assume MH_step is a handle to the method above MethodType loopType = methodType(String.class, String.class, int.class, String.class); MethodHandle count = MethodHandles.dropArgumentsToMatch(MethodHandles.identity(int.class), 0, loopType.parameterList(), 1); MethodHandle start = MethodHandles.dropArgumentsToMatch(MethodHandles.identity(String.class), 0, loopType.parameterList(), 2); MethodHandle body = MethodHandles.dropArgumentsToMatch(MH_step, 2, loopType.parameterList(), 0); MethodHandle loop = MethodHandles.countedLoop(count, start, body); // (v, i, pre, _, _) -> pre + " " + v assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("na", 13, "Lambdaman!"));
MethodHandle countedLoop(MethodHandle iterations, MethodHandle init, MethodHandle body) { return countedLoop(empty(iterations.type()), iterations, init, body); }
- パラメータ:
iterations
- このループが実行する反復回数を戻すnull
以外のハンドル。 ハンドルの結果タイプはint
である必要があります。 その他の制約については、上記を参照してください。init
- オプションのイニシャライザ。ループ変数の初期値を指定します。null
の場合があり、デフォルトの初期値を示します。 その他の制約については、上記を参照してください。body
- ループの本文。null
にはできません。 標準ケース(詳細は上記を参照)でループ・パラメータと結果型を制御します。 独自の戻り型(非空白の場合)とint
パラメータ(カウンタのために)を受け入れる必要があり、任意の数の追加型を受け入れることができます。 その他の制約については、上記を参照してください。- 戻り値:
- ループを表すメソッド・ハンドル。
- 例外:
NullPointerException
-iterations
またはbody
ハンドルのいずれかがnull
の場合。IllegalArgumentException
- いずれかの引数が上記の規則に違反している場合。- 導入されたバージョン:
- 9
- 関連項目:
-
countedLoop
public static MethodHandle countedLoop(MethodHandle start, MethodHandle end, MethodHandle init, MethodHandle body) 数値の範囲にわたってカウントするループを構築します。 これは「汎用ループ・コンビネータ」の便利なラッパーです。ループ・カウンタ
i
は、型int
のループ反復変数です。start
およびend
ハンドルは、ループ・カウンタの開始(inclusive)および終了(exclusive)の値を決定します。 ループ・カウンタは、start
ハンドルの評価から返されたint
値に初期化され、ステップ幅1でend
(exclusively)から返された値に実行されます。body
ハンドルがvoid
型以外のV
を返す場合、その型の先行ループ反復変数も存在します。 この変数は、オプションのinit
ハンドルを使用して、またはV
タイプの「デフォルト値」(ハンドルがnull
の場合)に初期化されます。各反復では、反復変数が
body
ハンドルの呼出しに渡されます。 本文(型V
の)から返されたvoid
以外の値は、先頭の反復変数を更新します。 ループ・ハンドル実行の結果は、その変数(V
変数がない場合はvoid
)の最後のV
値になります。引き数ハンドルには次の規則があります:
start
ハンドルとend
ハンドルは、null
であってはなりません。また、パラメータ型リストでI
と呼ばれる共通型int
も返す必要があります。body
ハンドルはnull
であってはなりません。その型は、(V I A...)V
の形式でなければなりません。ここで、V
は非void
です。そうでなければ(I A...)void
です。 (void
の場合、void
型をV
という名前に割り当て、void
型V
がパラメータ・リストから静かに削除され、(I A...)V
が残ることを理解して(V I A...)V
を記述します。)- 本文のパラメータ・リスト
(V I A...)
は、「内部パラメータ・リスト」と呼ばれる型のリストに寄与します。 他のループ部分のパラメータ・リストを制約します。 - 特殊なケースとして、本文が
V
型およびI
型のみを提供し、追加のA
型がない場合、内部パラメータ・リストは、end
ハンドルの引数型A...
によって拡張されます。 - 反復変数タイプ
(V I)
が内部パラメータ・リストから削除されると、結果の短いリスト(A...)
が「外部パラメータ・リスト」と呼ばれます。 - 本文の戻り型
V
は、void
以外の場合、ループの追加状態変数の型を決定します。 本文は先行するパラメータを受け入れ、この型の値V
を戻す必要があります。 init
が非null
の場合、戻り型はV
でなければなりません。 そのパラメータ・リスト(いくつかの「フォーム(A*)
」の)は、外部パラメータ・リスト(A...)
に対して「効果的に同一」でなければなりません。init
がnull
の場合、ループ変数は「デフォルト値」に初期化されます。start
(いくつかの形式の(A*)
)のパラメータ・リストは、外部パラメータ・リスト(A...)
と実質的に同一でなければなりません。- 同様に、
end
のパラメータ・リストは、外部パラメータ・リストと実質的に同じである必要があります。
結果のループ・ハンドルの結果タイプとパラメータ・シグネチャは、次のように決定されます:
- ループ・ハンドルの結果タイプは、本文の結果タイプ
V
です。 - ループ・ハンドルのパラメータ・タイプは、外部パラメータ・リストの
(A...)
型です。
結果のループ・ハンドルの疑似コードを次に示します。 コードでは、
V
/v
は2番目のループ変数の型/値およびループの結果型を表し、A...
/a...
はループに渡される引数を表します。int start(A...); int end(A...); V init(A...); V body(V, int, A...); V countedLoop(A... a...) { int e = end(a...); int s = start(a...); V v = init(a...); for (int i = s; i < e; ++i) { v = body(v, i, a...); } return v; }
- APIのノート:
- このメソッドの実装は、以下のように表すことができる:
MethodHandle countedLoop(MethodHandle start, MethodHandle end, MethodHandle init, MethodHandle body) { MethodHandle returnVar = dropArguments(identity(init.type().returnType()), 0, int.class, int.class); // assume MH_increment and MH_predicate are handles to implementation-internal methods with // the following semantics: // MH_increment: (int limit, int counter) -> counter + 1 // MH_predicate: (int limit, int counter) -> counter < limit Class<?> counterType = start.type().returnType(); // int Class<?> returnType = body.type().returnType(); MethodHandle incr = MH_increment, pred = MH_predicate, retv = null; if (returnType != void.class) { // ignore the V variable incr = dropArguments(incr, 1, returnType); // (limit, v, i) => (limit, i) pred = dropArguments(pred, 1, returnType); // ditto retv = dropArguments(identity(returnType), 0, counterType); // ignore limit } body = dropArguments(body, 0, counterType); // ignore the limit variable MethodHandle[] loopLimit = { end, null, pred, retv }, // limit = end(); i < limit || return v bodyClause = { init, body }, // v = init(); v = body(v, i) indexVar = { start, incr }; // i = start(); i = i + 1 return loop(loopLimit, bodyClause, indexVar); }
- パラメータ:
start
- ループ・カウンタの開始値を返すnull
以外のハンドル。これはint
である必要があります。 その他の制約については、上記を参照してください。end
- ループ・カウンタ(ループはend-1
に実行されます)の終了値を返す非null
ハンドル。 結果の型はint
でなければなりません。 その他の制約については、上記を参照してください。init
- オプションのイニシャライザ。ループ変数の初期値を指定します。null
の場合があり、デフォルトの初期値を示します。 その他の制約については、上記を参照してください。body
- ループの本文。null
にはできません。 標準ケース(詳細は上記を参照)でループ・パラメータと結果型を制御します。 独自の戻り型(非空白の場合)とint
パラメータ(カウンタのために)を受け入れる必要があり、任意の数の追加型を受け入れることができます。 その他の制約については、上記を参照してください。- 戻り値:
- ループを表すメソッド・ハンドル。
- 例外:
NullPointerException
-start
、end
、またはbody
ハンドルのいずれかがnull
である場合。IllegalArgumentException
- いずれかの引数が上記の規則に違反している場合。- 導入されたバージョン:
- 9
- 関連項目:
-
iteratedLoop
public static MethodHandle iteratedLoop(MethodHandle iterator, MethodHandle init, MethodHandle body) Iterator<T>
によって生成された値の範囲にあるループを構築します。 これは「汎用ループ・コンビネータ」の便利なラッパーです。イテレータ自体は、
iterator
ハンドルの評価によって決定されます。 生成される各値は、型T
のループ反復変数に格納されます。body
ハンドルがvoid
型以外のV
を返す場合、その型の先行ループ反復変数も存在します。 この変数は、オプションのinit
ハンドルを使用して、またはV
タイプの「デフォルト値」(ハンドルがnull
の場合)に初期化されます。各反復では、反復変数が
body
ハンドルの呼出しに渡されます。 本文(型V
の)から返されたvoid
以外の値は、先頭の反復変数を更新します。 ループ・ハンドル実行の結果は、その変数(V
変数がない場合はvoid
)の最後のV
値になります。引き数ハンドルには次の規則があります:
body
ハンドルはnull
であってはなりません。その型は、(V T A...)V
の形式でなければなりません。ここで、V
は非void
です。そうでなければ(T A...)void
です。 (void
の場合、void
型をV
という名前に割り当て、void
型V
がパラメータ・リストから静かに削除され、(T A...)V
が残ることを理解して(V T A...)V
を記述します。)- 本文のパラメータ・リスト
(V T A...)
は、「内部パラメータ・リスト」と呼ばれる型のリストに寄与します。 他のループ部分のパラメータ・リストを制約します。 - 特殊なケースとして、本文が
V
型およびT
型のみを提供し、追加のA
型がない場合、内部パラメータ・リストは、iterator
ハンドルの引数型A...
によって拡張されます。null
の場合、単一の型Iterable
が追加され、A...
リストが構成されます。 - 反復変数タイプ
(V T)
が内部パラメータ・リストから削除されると、結果の短いリスト(A...)
が「外部パラメータ・リスト」と呼ばれます。 - 本文の戻り型
V
は、void
以外の場合、ループの追加状態変数の型を決定します。 本文は先行するパラメータを受け入れ、この型の値V
を戻す必要があります。 init
が非null
の場合、戻り型はV
でなければなりません。 そのパラメータ・リスト(いくつかの「フォーム(A*)
」の)は、外部パラメータ・リスト(A...)
に対して「効果的に同一」でなければなりません。init
がnull
の場合、ループ変数は「デフォルト値」に初期化されます。iterator
ハンドルがnull
以外の場合、戻り型はjava.util.Iterator
またはサブタイプである必要があります。 ループが実行されたときに生成されるイテレータは、T
型に変換可能な値を生成すると見なされます。- 非
null
(いくつかの形式の(A*)
の)であるiterator
のパラメータ・リストは、外部パラメータ・リスト(A...)
と実質的に同一でなければなりません。 iterator
がnull
の場合、デフォルトではIterable.iterator()
のように動作するメソッド・ハンドルになります。 その場合、内部パラメータ・リスト(V T A...)
には少なくとも1つのA
タイプが必要です。また、デフォルトのイテレータ・ハンドル・パラメータは、asType
変換メソッドの場合と同様に、先頭のA
タイプを受け入れるように調整されます。 先頭のA
型は、Iterable
またはそのサブタイプである必要があります。 この変換ステップは、ループ構築時に実行され、WrongMethodTypeException
をスローしないでください。
T
型は、プリミティブまたは参照のいずれかです。Iterator<T>
型はメソッド・ハンドル表現でRAW型Iterator
に消去されるため、iteratedLoop
コンビネータは、body
のObject
への先頭引数型をasType
変換メソッドによって調整します。 したがって、ループの実行時に間違ったタイプのイテレータが表示される場合、MethodHandle.asType(MethodType)
によって実行される動的変換の結果として実行時例外が発生する可能性があります。結果のループ・ハンドルの結果タイプとパラメータ・シグネチャは、次のように決定されます:
- ループ・ハンドルの結果タイプは、本文の結果タイプ
V
です。 - ループ・ハンドルのパラメータ・タイプは、外部パラメータ・リストの
(A...)
型です。
結果のループ・ハンドルの疑似コードを次に示します。 コードでは、
V
/v
はループ変数の型/値およびループの結果型を表し、T
/t
はループが反復する構造の要素の型を表し、A...
/a...
はループに渡される引数を表します。Iterator<T> iterator(A...); // defaults to Iterable::iterator V init(A...); V body(V,T,A...); V iteratedLoop(A... a...) { Iterator<T> it = iterator(a...); V v = init(a...); while (it.hasNext()) { T t = it.next(); v = body(v, t, a...); } return v; }
- APIのノート:
- 例:
// get an iterator from a list static List<String> reverseStep(List<String> r, String e) { r.add(0, e); return r; } static List<String> newArrayList() { return new ArrayList<>(); } // assume MH_reverseStep and MH_newArrayList are handles to the above methods MethodHandle loop = MethodHandles.iteratedLoop(null, MH_newArrayList, MH_reverseStep); List<String> list = Arrays.asList("a", "b", "c", "d", "e"); List<String> reversedList = Arrays.asList("e", "d", "c", "b", "a"); assertEquals(reversedList, (List<String>) loop.invoke(list));
MethodHandle iteratedLoop(MethodHandle iterator, MethodHandle init, MethodHandle body) { // assume MH_next, MH_hasNext, MH_startIter are handles to methods of Iterator/Iterable Class<?> returnType = body.type().returnType(); Class<?> ttype = body.type().parameterType(returnType == void.class ? 0 : 1); MethodHandle nextVal = MH_next.asType(MH_next.type().changeReturnType(ttype)); MethodHandle retv = null, step = body, startIter = iterator; if (returnType != void.class) { // the simple thing first: in (I V A...), drop the I to get V retv = dropArguments(identity(returnType), 0, Iterator.class); // body type signature (V T A...), internal loop types (I V A...) step = swapArguments(body, 0, 1); // swap V <-> T } if (startIter == null) startIter = MH_getIter; MethodHandle[] iterVar = { startIter, null, MH_hasNext, retv }, // it = iterator; while (it.hasNext()) bodyClause = { init, filterArguments(step, 0, nextVal) }; // v = body(v, t, a) return loop(iterVar, bodyClause); }
- パラメータ:
iterator
- ループを開始するイテレータを返すオプションのハンドル。null
以外の場合、ハンドルはIterator
またはサブタイプを返す必要があります。 その他の制約については、上記を参照してください。init
- オプションのイニシャライザ。ループ変数の初期値を指定します。null
の場合があり、デフォルトの初期値を示します。 その他の制約については、上記を参照してください。body
- ループの本文。null
にはできません。 標準ケース(詳細は上記を参照)でループ・パラメータと結果型を制御します。 独自の戻り型(非空白の場合)とT
パラメータ(反復された値)を受け入れる必要があり、任意の数の追加型を受け入れることができます。 その他の制約については、上記を参照してください。- 戻り値:
- 反復ループ機能を具現化するメソッド・ハンドル。
- 例外:
NullPointerException
-body
ハンドルがnull
の場合。IllegalArgumentException
- いずれかの引数が上記の要件に違反している場合。- 導入されたバージョン:
- 9
-
tryFinally
public static MethodHandle tryFinally(MethodHandle target, MethodHandle cleanup) target
メソッド・ハンドルをtry-finally
ブロックにラップして適応させるメソッド・ハンドルを作成します。 別のメソッド・ハンドルcleanup
は、finally
ブロックの機能を表します。target
ハンドルの実行中にスローされた例外は、cleanup
ハンドルに渡されます。cleanup
ハンドルが最初に例外をスローしないかぎり、例外は再スローされます。cleanup
ハンドルの実行から返される値は、try-finally
ハンドルの実行結果になります。cleanup
ハンドルには、1つまたは2つの追加の先行引数が渡されます。 1つ目は、target
ハンドルの実行中にスローされた例外、または例外がスローされなかった場合はnull
です。 2つ目は、target
ハンドルの実行の結果です。または、例外をスローすると、必要な型のnull
、ゼロまたはfalse
値がプレースホルダーとして提供されます。target
ハンドルにvoid
戻り型がある場合、2番目の引数は存在しません。 (引数型変換を除き、コンビネータは、null
またはゼロ値を挿入するのではなく、対応する逆説引数を省略して、パラメータ・リスト内のvoid
値を表します。)target
ハンドルとcleanup
ハンドルは、対応する引数と戻り型が同じである必要があります。ただし、cleanup
ハンドルは後続引数を省略できます。 また、cleanup
ハンドルには、1つまたは2つの先行パラメータが必要です:Throwable
は、target
は、target
ハンドル(もしあれば)によってスローされた例外を運びます。そしてtarget
およびcleanup
の両方の戻り型と同じ型のパラメータ。このパラメータは、target
ハンドルの実行の結果を保持します。target
がvoid
を返した場合、このパラメータは存在しません。
結果のアダプタの疑似コードは次のようになります。 コード内の
V
は、try/finally
構成の結果型、A
/a
、クリーンアップによって消費される結果ハンドルの引数の型と値、およびB
/b
、クリーンアップによって破棄される結果ハンドルの引数の型と値を表します。V target(A..., B...); V cleanup(Throwable, V, A...); V adapter(A... a, B... b) { V result = (zero value for V); Throwable throwable = null; try { result = target(a..., b...); } catch (Throwable t) { throwable = t; throw t; } finally { result = cleanup(throwable, result, a...); } return result; }
保存された引数(擬似コード内の
a...
)は、ターゲットの実行によって変更できないため、コール元からクリーンアップ(起動された場合)に変更なしで渡されることに注意してください。クリーンアップが常にスローされる場合でも、ターゲットとクリーンアップは同じタイプを返す必要があります。 このようなスロー・クリーンアップを作成するには、正しい戻り型のメソッド・ハンドルを作成するために、
throwException
を使用してクリーンアップ・ロジックを作成します。tryFinally
は、例外を通常の戻り値に変換しないことに注意してください。 そのように例外を変換する必要があるまれなケースでは、まずターゲットをcatchException(MethodHandle, Class, MethodHandle)
でラップして送信例外を取得し、次にtryFinally
でラップします。cleanup
の最初のパラメータ・タイプは、専用サブタイプではなくThrowable
を宣言することをお薦めします。 これにより、target
がスローする例外を除き、常にcleanup
が起動されるようになります。 絞込みタイプを宣言すると、try-finally
によってスローされた例外のタイプがtarget
によってスローされた例外のタイプがcleanup
の最初のパラメータ・タイプに代入できない場合に、ClassCastException
がスローされる可能性があります。VirtualMachineError
、LinkageError
およびRuntimeException
の様々な例外タイプは、ほとんどすべての種類のJavaコードが原理内でスローされる可能性があることに注意してください。(例)のみを捕捉するfinally句は、IOException
3 codektj 4コードの外部キーをマスクします。- パラメータ:
target
- 実行をtry
ブロックにラップするハンドル。cleanup
- 最終ブロックで呼び出されるハンドル。- 戻り値:
- 2つの引数で構成される
try-finally
ブロックを形成するメソッド・ハンドル。 - 例外:
NullPointerException
- いずれかの引数がnullの場合IllegalArgumentException
-cleanup
が必須の先行引数を受け入れない場合、またはメソッド・ハンドルの型が戻り型とそれに対応する末尾のパラメータと一致しない場合- 導入されたバージョン:
- 9
- 関連項目:
-
tableSwitch
public static MethodHandle tableSwitch(MethodHandle fallback, MethodHandle... targets) 表スイッチ・メソッド・ハンドルを作成します。これは、セレクタと呼ばれる特定のターゲット索引に基づいて、ターゲット・メソッド・ハンドルのセットを切り替えるために使用できます。セレクタ値
n
(n
は[0, N)
の範囲内にあり、N
はターゲット・メソッド・ハンドルの数)の場合、表スイッチ・メソッド・ハンドルは、ターゲット・メソッド・ハンドルのリストからn番目のターゲット・メソッド・ハンドルを起動します。[0, N)
の範囲内にないセレクタ値の場合、表スイッチ・メソッド・ハンドルは指定されたフォールバック・メソッド・ハンドルを起動します。このメソッドに渡すメソッド・ハンドルはすべて同じタイプである必要があり、先行するパラメータが
int
タイプであるという追加の要件があります。 先頭パラメータはセレクタを表します。型に存在する後続のパラメータも、返されるテーブル・スイッチ・メソッド・ハンドルに表示されます。 これらのパラメータに割り当てられた引数は、セレクタ値と共に、起動時に選択したメソッド・ハンドルに転送されます。
- APIのノート:
- 例: 各ケースでは、指定された
selector
値をドロップし、(String.concat(String)
を使用して)を特定の定数ラベル文字列に連結した追加のString
引数を使用します:MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodHandle caseMh = lookup.findVirtual(String.class, "concat", MethodType.methodType(String.class, String.class)); caseMh = MethodHandles.dropArguments(caseMh, 0, int.class); MethodHandle caseDefault = MethodHandles.insertArguments(caseMh, 1, "default: "); MethodHandle case0 = MethodHandles.insertArguments(caseMh, 1, "case 0: "); MethodHandle case1 = MethodHandles.insertArguments(caseMh, 1, "case 1: "); MethodHandle mhSwitch = MethodHandles.tableSwitch( caseDefault, case0, case1 ); assertEquals("default: data", (String) mhSwitch.invokeExact(-1, "data")); assertEquals("case 0: data", (String) mhSwitch.invokeExact(0, "data")); assertEquals("case 1: data", (String) mhSwitch.invokeExact(1, "data")); assertEquals("default: data", (String) mhSwitch.invokeExact(2, "data"));
- パラメータ:
fallback
- セレクタが[0, N)
の範囲外の場合にコールされるフォールバック・メソッド・ハンドル。targets
- ターゲット・メソッド・ハンドルの配列。- 戻り値:
- 表スイッチ・メソッド・ハンドル。
- 例外:
NullPointerException
-fallback
の場合、targets
配列、またはtargets
配列の要素のいずれかがnull
です。IllegalArgumentException
-targets
配列が空の場合、フォールバック・ハンドルまたはいずれかのターゲット・ハンドルの先頭パラメータがint
でない場合、またはフォールバック・ハンドルのタイプとすべてのターゲット・ハンドルが同じでない場合。
-
filterValue
public static VarHandle filterValue(VarHandle target, MethodHandle filterToTarget, MethodHandle filterFromTarget) フィルタ関数のペアを使用して受信値と送信値を事前処理することで、ターゲット変数ハンドルを適応させます。たとえば、結果のvarハンドルで
VarHandle.set(Object...)
をコールすると、最初のフィルタを使用して受信値(T
タイプ。T
は最初のフィルタ関数のlastパラメータ・タイプです。)が処理され、ターゲットのvarハンドルに渡されます。 逆に、結果のvarハンドルで、たとえば、VarHandle.get(Object...)
などをコールすると、ターゲットのvarハンドル(T
タイプ。T
は、2番目のフィルタ関数のlastパラメータ・タイプです。)から取得された戻り値は、2番目のフィルタを使用して処理され、コール元に戻されます。VarHandle.AccessMode.COMPARE_AND_EXCHANGE
などのより高度なアクセス・モード・タイプでは、両方のフィルタが同時に適用される場合があります。ボクシング・フィルタおよびアンボックス・フィルタを整形式にするには、それぞれ
(A... , S) -> T
および(A... , T) -> S
の形式にする必要があります(T
はターゲット変数ハンドルのタイプです)。 この場合、結果のvarハンドルはS
型になり、追加の座標A...
(ターゲット変数ハンドルの座標に追加されます。)を特徴とします。ボクシング・フィルタおよびアンボックス化フィルタが呼び出されたときにチェック例外をスローすると、結果のvarハンドルは
IllegalStateException
をスローします。結果のvarハンドルには、ターゲットのvarハンドルの機能と同じアクセス・モードである(
VarHandle.AccessMode
を参照してください)およびアトミック・アクセスが保証されます。- パラメータ:
target
- ターゲット変数ハンドルfilterToTarget
- 一部のタイプのS
をtarget
のタイプに変換するフィルタfilterFromTarget
-target
のタイプをS
のタイプに変換するフィルタ- 戻り値:
- 指定されたボクシング/アン・ボクシング変換を実行して、新しい型を受け入れるアダプタ変数ハンドル。
- 例外:
IllegalArgumentException
-filterFromTarget
およびfilterToTarget
の形式が適切でない場合、つまり、それぞれ(A... , S) -> T
および(A... , T) -> S
以外の型があり、T
はターゲット変数ハンドルのタイプであるか、filterFromTarget
またはfilterToTarget
のいずれかがチェックされた例外をスローすると判断された場合。NullPointerException
- 引数のいずれかがnull
の場合。- 導入されたバージョン:
- 22
-
filterCoordinates
public static VarHandle filterCoordinates(VarHandle target, int pos, MethodHandle... filters) 単項フィルタ関数を使用して着信座標値を前処理することで、ターゲット変数ハンドルを適応させます。たとえば、結果のvarハンドルで
VarHandle.get(Object...)
をコールすると、pos
(C1, C2 ... Cn
型(C1, C2 ... Cn
は単項フィルタ関数の戻り型))の位置から始まる着信座標値が新しい値(S1, S2 ... Sn
型。S1, S2 ... Sn
は単項フィルタ関数のパラメータ型です。)に変換され、(適応によって変更されていない座標とともに)がターゲットのvarハンドルに渡されます。座標フィルタを整形式にするには、
S1 -> T1, S2 -> T1 ... Sn -> Tn
の形式にする必要があります。T1, T2 ... Tn
は、ターゲット変数ハンドルの位置pos
から始まる座標タイプです。いずれかのフィルタが呼び出されたときにチェック例外をスローした場合、結果のvarハンドルは
IllegalStateException
をスローします。結果のvarハンドルには、ターゲットのvarハンドルの機能と同じアクセス・モードである(
VarHandle.AccessMode
を参照してください)およびアトミック・アクセスが保証されます。- パラメータ:
target
- ターゲット変数ハンドルpos
- 変換する最初の座標の位置filters
- 位置pos
から座標を変換するために使用される単項関数- 戻り値:
- 指定された変換を新しい座標値に適用して、新しい座標型を受け入れるアダプタ変数ハンドル。
- 例外:
IllegalArgumentException
-filters
のハンドルが整形式でない場合、つまり、S1 -> T1, S2 -> T2, ... Sn -> Tn
以外のタイプがあり、pos
が0の間でない場合は、T1, T2 ... Tn
はターゲット変数ハンドルの位置pos
から始まる座標タイプです。また、ターゲット変数ハンドルの座標アリティ(包含)や、pos
から始まる実際の座標タイプ数よりも多くのフィルタが指定されている場合、またはいずれかのフィルタがチェックされた例外をスローすることを決定した場合。NullPointerException
- 引数のいずれかがnull
であるか、filters
にnull
が含まれている場合。- 導入されたバージョン:
- 22
-
insertCoordinates
Varハンドル呼出しの前に、1つ以上の「バインド座標」を持つターゲットvarハンドルを提供します。 その結果、結果のvarハンドルは、ターゲットのvarハンドルよりも座標型が少なくなります。たとえば、結果のvarハンドルで
VarHandle.get(Object...)
をコールすると、着信座標値がバインドされた座標値と結合され、ターゲットのvarハンドルに渡されます。境界座標を整形するには、その型は
T1, T2 ... Tn
である必要があります。T1, T2 ... Tn
は、ターゲット変数ハンドルの位置pos
から始まる座標タイプです。結果のvarハンドルには、ターゲットのvarハンドルの機能と同じアクセス・モードである(
VarHandle.AccessMode
を参照してください)およびアトミック・アクセスが保証されます。- パラメータ:
target
- バインドされた座標が挿入された後に呼び出すvarハンドルpos
- 挿入する最初の座標の位置values
- 挿入する一連のバウンド座標- 戻り値:
- ターゲットvarハンドルをコールする前に追加の座標を挿入するアダプタvarハンドル
- 例外:
IllegalArgumentException
-pos
が0からターゲットのvarハンドル座標引数(両端を含む)の間にない場合、またはpos
から使用可能な座標タイプの実際の数よりも多くの値が指定されている場合。ClassCastException
-values
のバインドされた座標が整形式でない場合、つまり、T1, T2 ... Tn
以外の型を持つ場合(T1, T2 ... Tn
はターゲット変数ハンドルのpos
の位置から始まる座標型です)。NullPointerException
- 引数のいずれかがnull
であるか、values
にnull
が含まれている場合。- 導入されたバージョン:
- 22
-
permuteCoordinates
public static VarHandle permuteCoordinates(VarHandle target, List<Class<?>> newCoordinates, int... reorder) 新しい座標が指定された座標と一致するように再配列することで、ターゲットのvarハンドルの座標値を適応させるvarハンドルを提供します。指定された配列によって並べ替えが制御されます。 着信座標数(値
newCoordinates.size()
)を#I
にコールし、発信座標数(ターゲット変数ハンドルに関連付けられた座標の数)を#O
にコールします。 このとき、並べ替え配列の長さは#O
、各要素は#I
より小さい負でない数でなければいけません。#O
未満のすべてのN
について、N
番目の送信座標は、I
がreorder[N]
であるI
番目の受信座標から取得されます。座標値の変換は適用されません。
newCoordinates
によって決定される各受信座標の型は、ターゲット変数ハンドル内の対応する送信座標の型と同じである必要があります。並べ替え配列では、実際の入れ替えを指定する必要はありません。 入力座標は、そのインデックスが配列内に複数回出現する場合は複製され、インデックスが配列内に存在しない場合は入力座標が削除されます。
結果のvarハンドルには、ターゲットのvarハンドルの機能と同じアクセス・モードである(
VarHandle.AccessMode
を参照してください)およびアトミック・アクセスが保証されます。- パラメータ:
target
- 座標が並べ替えられた後に呼び出すvarハンドルnewCoordinates
- 新しい座標型reorder
- 並べ替えを制御するインデックス配列- 戻り値:
- ターゲットのvarハンドルを呼び出す前に、着信座標値を再配置するアダプタのvarハンドル
- 例外:
IllegalArgumentException
- 索引配列の長さがターゲットのvarハンドルの座標数と等しくない場合、索引配列要素がnewCoordinates
の座標に対して有効な索引でない場合、またはターゲットのvarハンドルとnewCoordinates
の対応する座標タイプが同じでない場合。NullPointerException
- 引数のいずれかがnull
であるか、newCoordinates
にnull
が含まれている場合。- 導入されたバージョン:
- 22
-
collectCoordinates
public static VarHandle collectCoordinates(VarHandle target, int pos, MethodHandle filter) フィルタ(メソッド・ハンドル)を使用して座標値のサブ・シーケンスを前処理することで、ターゲット変数ハンドルを調整します。 前処理された座標はフィルタ関数の結果(もしあれば)に置き換えられ、変更された(通常は短縮)座標リストでターゲット変数ハンドルが呼び出されます。R
がフィルタの戻り型の場合:R
がvoid
でない場合、ターゲットのvarハンドルには、位置pos
にR
型の座標が必要です。 フィルタのパラメータ型は、ターゲットvarハンドルの位置pos
にある座標型を置換します。 戻されたvarハンドルが呼び出されると、フィルタが最初に呼び出されたかのようになり、ターゲットvarハンドルのダウンストリーム呼出しで位置pos
の座標のかわりにその結果が渡されます。-
R
がvoid
の場合、フィルタのパラメータ型(もしあれば)は、位置pos
のターゲットvarハンドルの座標型リストに挿入されます。 この場合、返されるvarハンドルが呼び出されると、フィルタは基本的に副作用として動作し、ターゲットvarハンドルのダウンストリーム呼出しの前に座標値の一部を使用します。
いずれかのフィルタが呼び出されたときにチェック例外をスローした場合、結果のvarハンドルは
IllegalStateException
をスローします。結果のvarハンドルには、ターゲットのvarハンドルの機能と同じアクセス・モードである(
VarHandle.AccessMode
を参照してください)およびアトミック・アクセスが保証されます。- パラメータ:
target
- 座標がフィルタ処理された後に呼び出すvarハンドルpos
- フィルタを挿入するターゲットvarハンドルの座標リスト内の位置filter
- フィルタ・メソッド・ハンドル- 戻り値:
- ターゲットのvarハンドルを呼び出す前に、着信座標値をフィルタ処理するアダプタのvarハンドル
- 例外:
IllegalArgumentException
-filter
の戻り型がvoidではなく、ターゲットVARハンドルのpos
座標と同じでない場合、pos
が0とターゲットVARハンドルの座標の配列の間にない場合、結果のVARハンドルの型に「座標が多すぎます」がある場合、またはfilter
がチェック済の例外をスローしていると判断された場合。NullPointerException
- 引数のいずれかがnull
の場合。- 導入されたバージョン:
- 22
-
dropCoordinates
ターゲットのvarハンドルに委譲する前にダミー座標を破棄するvarハンドルを返します。 その結果、結果のvarハンドルは、ターゲットのvarハンドルよりも座標型が多くなります。pos
引数の範囲はゼロからNです。ここで、Nはターゲットのvarハンドル座標型の引数です。pos
がゼロの場合、ダミー座標はターゲットの実引数の前に配置され、pos
がNの場合は後ろに配置されます。結果のvarハンドルには、ターゲットのvarハンドルの機能と同じアクセス・モードである(
VarHandle.AccessMode
を参照してください)およびアトミック・アクセスが保証されます。- パラメータ:
target
- ダミー座標がドロップされた後に呼び出すvarハンドルpos
- (左端のゼロ)を削除する最初の座標の位置valueTypes
- ドロップする座標の型- 戻り値:
- ターゲットvarハンドルを呼び出す前にダミー座標をドロップするアダプタvarハンドル
- 例外:
IllegalArgumentException
-pos
が0からターゲットのvarハンドル座標引数(両端を含む)の間にない場合。NullPointerException
- 引数のいずれかがnull
であるか、valueTypes
にnull
が含まれている場合。- 導入されたバージョン:
- 22
-