public class MethodHandles extends Object
修飾子と型 | クラスと説明 |
---|---|
static class |
MethodHandles.Lookup
ルックアップオブジェクトは、メソッドハンドルの作成にアクセスチェックが必要な場合のメソッドハンドル作成用ファクトリです。
|
修飾子と型 | メソッドと説明 |
---|---|
static MethodHandle |
arrayElementGetter(Class<?> arrayClass)
配列の各要素に対する読み取りアクセスを提供するメソッドハンドルを生成します。
|
static MethodHandle |
arrayElementSetter(Class<?> arrayClass)
配列の各要素に対する書き込みアクセスを提供するメソッドハンドルを生成します。
|
static MethodHandle |
catchException(MethodHandle target, Class<? extends Throwable> exType, MethodHandle handler)
ターゲットのメソッドハンドルを例外ハンドラの内部で実行することによって、このターゲットを適応させるメソッドハンドルを作成します。
|
static MethodHandle |
constant(Class<?> type, Object value)
要求された戻り値の型を持ち、呼び出されるたびに指定された定数値を返すメソッドハンドルを生成します。
|
static MethodHandle |
dropArguments(MethodHandle target, int pos, Class<?>... valueTypes)
いくつかのダミー引数を破棄してから指定された別の target メソッドハンドルを呼び出すメソッドハンドルを生成します。
|
static MethodHandle |
dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes)
いくつかのダミー引数を破棄してから指定された別の target メソッドハンドルを呼び出すメソッドハンドルを生成します。
|
static MethodHandle |
exactInvoker(MethodType type)
特殊なインボーカメソッドハンドルを生成します (これを使用すれば、指定された型の任意のメソッドハンドルを、
invokeExact を使用する場合と同様に呼び出すことができる)。 |
static MethodHandle |
explicitCastArguments(MethodHandle target, MethodType newType)
指定されたメソッドハンドルの型を新しい型に適応させるために、引数と戻り値の型の変換をペア単位で行うメソッドハンドルを生成します。
|
static MethodHandle |
filterArguments(MethodHandle target, int pos, MethodHandle... filters)
ターゲットメソッドハンドルを適応させるため、その 1 つ以上の引数をそれぞれ固有の単項フィルタ関数を使って前処理したあと、前処理を行なった各引数を対応するフィルタ関数の結果で置き換えてターゲットを呼び出します。
|
static MethodHandle |
filterReturnValue(MethodHandle target, MethodHandle filter)
ターゲットメソッドハンドルを適応させるため、その戻り値 (存在する場合) をフィルタ (別のメソッドハンドル) で後処理します。
|
static MethodHandle |
foldArguments(MethodHandle target, MethodHandle combiner)
ターゲットメソッドハンドルを適応させるため、その引数のいくつかを前処理したあと、前処理の結果を元の一連の引数内に挿入してターゲットを呼び出します。
|
static MethodHandle |
guardWithTest(MethodHandle test, MethodHandle target, MethodHandle fallback)
テスト (boolean 値のメソッドハンドル) で保護することでターゲットメソッドハンドルを適応させるメソッドハンドルを作成します。
|
static MethodHandle |
identity(Class<?> type)
呼び出し時に唯一の引数の値を返すメソッドハンドルを生成します。
|
static MethodHandle |
insertArguments(MethodHandle target, int pos, Object... values)
ターゲットメソッドハンドルの呼び出しの前に、1 つ以上のバインド引数をメソッドハンドルに提供します。
|
static MethodHandle |
invoker(MethodType type)
特殊なインボーカメソッドハンドルを生成します (これを使用すれば、指定された型と互換性のある任意のメソッドハンドルを、
invoke を使用する場合と同様に呼び出すことができる)。 |
static MethodHandles.Lookup |
lookup()
呼び出し元がアクセス可能な任意のメソッドハンドル (private なフィールドやメソッドへの直接メソッドハンドルを含む) へのアクセス機能を備えた、呼び出し元の
ルックアップオブジェクト を返します。 |
static MethodHandle |
permuteArguments(MethodHandle target, MethodType newType, int... reorder)
引数の順序を変更することによって、指定されたメソッドハンドルの呼び出し順序を新しい型に適応させるメソッドハンドルを生成します。
|
static MethodHandles.Lookup |
publicLookup()
最小の信頼レベルを持つ
ルックアップオブジェクト を返します。 |
static MethodHandle |
spreadInvoker(MethodType type, int leadingArgCount)
指定された
type の任意のメソッドハンドルを呼び出すメソッドハンドルを生成しますが、その際、指定された数の末尾の引数が単一の末尾の Object[] 配列で置き換えられます。 |
static MethodHandle |
throwException(Class<?> returnType, Class<? extends Throwable> exType)
指定された
exType の例外をスローするメソッドハンドルを生成します。 |
public static MethodHandles.Lookup lookup()
ルックアップオブジェクト
を返します。このルックアップオブジェクトは、信頼できるエージェントに委譲可能な 1 つの機能です。信頼できないコードからアクセス可能な場所に格納しないでください。public static MethodHandles.Lookup publicLookup()
ルックアップオブジェクト
を返します。これは、public のアクセス可能なフィールドやメソッドへのメソッドハンドルを作成する場合にのみ使用できます。
単に慣例により、このルックアップオブジェクトのルックアップクラスは、Object
になります。
ルックアップクラスをほかの任意のクラス C
に変更するには、publicLookup().in(C.class)
という形式の式を使用します。public の名前に対するアクセスはどのクラスもすべて同じであるため、そのような変更によって新しいアクセス権が付与されることはありません。
public static MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException
int
になります。arrayClass
- 配列の型NullPointerException
- 引数が null の場合IllegalArgumentException
- arrayClass が配列型でない場合public static MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException
NullPointerException
- 引数が null の場合IllegalArgumentException
- arrayClass が配列型でない場合public static MethodHandle spreadInvoker(MethodType type, int leadingArgCount)
type
の任意のメソッドハンドルを呼び出すメソッドハンドルを生成しますが、その際、指定された数の末尾の引数が単一の末尾の Object[]
配列で置き換えられます。結果となるインボーカは、次の引数を持つメソッドハンドルです。
MethodHandle
ターゲット
leadingArgCount
)
Object[]
配列
インボーカがそのターゲットを呼び出す方法は、示された type
を使用した invoke
の呼び出しに似ています。つまりその動作は、ターゲットの型が指定された type
と完全に等しい場合は invokeExact
のようになり、それ以外の場合は、asType
を使ってターゲットを必要な type
に変換するような動作になります。
返されるインボーカの型は、指定された type
ではなく、最初の leadingArgCount
個を除くすべてのパラメータが単一の Object[]
型配列で置き換えられたものとなり、これが最後のパラメータになります。
インボーカはそのターゲットを呼び出す前に、最後の配列を分配し、参照キャストを必要に応じて適用するほか、プリミティブ引数のアンボクシングやワイドニングを行います。
このメソッドは次のコードと同等です (ただし、効率はおそらくこのメソッドのほうが高い)。
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()
(両端を含む) の範囲に含まれていない場合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
- 目的となるターゲットの型public static MethodHandle invoker(MethodType type)
invoke
を使用する場合と同様に呼び出すことができる)。結果となるインボーカの型は、MethodHandle
型の追加の先頭の引数を 1 つ受け取る点を除けば、目的の型とまったく等しくなります。
ターゲットが期待される型と異なっている場合、インボーカはそのターゲットを呼び出す前に、asType
の場合と同じように、参照キャストを必要に応じて適用するほか、プリミティブ値のボクシング、アンボクシング、またはワイドニングを行います。同様に、戻り値も必要に応じて変換されます。ターゲットが可変引数メソッドハンドルの場合は、やはり asType
の場合と同じように、必要な引数変換が行われます。
汎用メソッド型では Object
型の引数や戻り値にのみ言及します。そのような型のインボーカは、引数の数が汎用型と同じメソッドハンドルであれば任意のものを呼び出すことができます。
このメソッドは次のコードと同等です (ただし、効率はおそらくこのメソッドのほうが高い)。
publicLookup().findVirtual(MethodHandle.class, "invoke", type)
このメソッドでは、リフレクションやセキュリティーに関する例外はスローされません。
type
- 目的となるターゲットの型public static MethodHandle explicitCastArguments(MethodHandle target, MethodType newType)
元の型と新しい型が等しい場合はターゲットを返します。
MethodHandle.asType
の場合と同じ変換が許可されるほか、それらの変換が失敗した場合には、いくつかの追加の変換も適用されます。asType
で行われる変換の前に、あるいはその代わりに、次のいずれかの変換が可能であれば適用されます (T0、T1 は型)。
(x & 1) != 0
と同様に行われます。
target
- 引数の型を調整したあとに呼び出すメソッドハンドルnewType
- 新しいメソッドハンドルの期待される型NullPointerException
- どちらかの引数が null の場合WrongMethodTypeException
- 変換できない場合MethodHandle.asType(java.lang.invoke.MethodType)
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 つのパラメータの型が同一でない場合public static MethodHandle constant(Class<?> type, Object value)
メソッドハンドルが返される前に、渡された値が要求された型に変換されます。要求された型がプリミティブの場合はプリミティブワイドニング変換が試みられ、それ以外の場合は参照変換が試みられます。
返されるメソッドハンドルは identity(type).bindTo(value)
と同等です。
type
- 必要なメソッドハンドルの戻り値の型value
- 返す値NullPointerException
- type
引数が null の場合ClassCastException
- 要求された戻り値の型に値を変換できない場合IllegalArgumentException
- 指定された型が void.class
の場合public static MethodHandle identity(Class<?> type)
type
- 必要なメソッドハンドルの唯一のパラメータと戻り値の型NullPointerException
- 引数が null の場合IllegalArgumentException
- 指定された型が void.class
の場合public static MethodHandle insertArguments(MethodHandle target, int pos, Object... values)
新しいメソッドハンドルの型には、元のターゲットの型に含まれていたバインドパラメータの型は含まれませんが、これは、新しいメソッドハンドルではもう、呼び出し元がそれらの引数を指定する必要がないからです。
指定された引数のオブジェクトはそれぞれ、対応するバインドパラメータの型に一致する必要があります。バインドパラメータの型がプリミティブの場合、引数のオブジェクトはラッパーである必要があり、オブジェクトがアンボクシングされてプリミティブ値が生成されます。
pos
引数によってバインドするパラメータが選択されます。その範囲は 0 - N-L (両端を含む) です。ここで、N はターゲットメソッドハンドルの引数長、L は値配列の長さです。
target
- 引数を挿入したあとに呼び出すメソッドハンドルpos
- 引数の挿入位置 (先頭の場合はゼロ)values
- 挿入する一連の引数NullPointerException
- ターゲットまたは values
配列が null の場合MethodHandle.bindTo(java.lang.Object)
public static MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes)
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
- 引数を除去したあとに呼び出すメソッドハンドルvalueTypes
- 除去する引数の型pos
- 除去する最初の引数の位置 (左端の場合は 0)NullPointerException
- ターゲットが null の場合、または valueTypes
リストまたはそのいずれかの要素が null の場合IllegalArgumentException
- valueTypes
のいずれかの要素が void.class
の場合、または pos
が負であるかターゲットの引数の数より大きい場合、または新しいメソッドハンドルの型に含まれるパラメータの数が多すぎる場合public static MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes)
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")); 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
- 引数を除去したあとに呼び出すメソッドハンドルvalueTypes
- 除去する引数の型pos
- 除去する最初の引数の位置 (左端の場合は 0)NullPointerException
- ターゲットが null の場合、または valueTypes
配列またはそのいずれかの要素が null の場合IllegalArgumentException
- valueTypes
のいずれかの要素が void.class
の場合、または pos
が負であるかターゲットの引数の数より大きい場合、または新しいメソッドハンドルの型に含まれるパラメータの数が多すぎる場合public static MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters)
前処理は、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
結果となるアダプタの擬似コードを次に示します。
V 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..., f[i](v[i])..., b...); }
target
- 引数をフィルタリングしたあとで呼び出すメソッドハンドルpos
- フィルタリングする最初の引数の位置filters
- フィルタリング対象の引数に対して最初に呼び出すメソッドハンドルNullPointerException
- ターゲットが null の場合または filters
配列が null の場合IllegalArgumentException
- 前述のように filters
の null でない要素がターゲットの対応する引数の型に一致しない場合、または pos+filters.length
が target.type().parameterCount()
よりも大きい場合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
結果となるアダプタの擬似コードを次に示します。
V target(A...); T filter(V); T adapter(A... a) { V v = target(a...); return filter(v); } // and if the target has a void return: void target2(A...); T filter2(); T adapter2(A... a) { target2(a...); return filter2(); } // and if the filter has a void return: V target3(A...); void filter3(V); void adapter3(A... a) { V v = target3(a...); filter3(v); }
target
- 戻り値をフィルタリングする前に呼び出すメソッドハンドルfilter
- 戻り値に対して呼び出すメソッドハンドルNullPointerException
- どちらかの引数が null の場合IllegalArgumentException
- 前述のように filter
の引数リストがターゲットの戻り値の型と一致しない場合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"));
結果となるアダプタの擬似コードを次に示します。
// 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
の引数の型と同一でない場合public static MethodHandle guardWithTest(MethodHandle test, MethodHandle target, MethodHandle fallback)
結果となるアダプタの擬似コードを次に示します。
テストの引数 (擬似コードでは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
- テストに失敗した場合に呼び出すメソッドハンドルNullPointerException
- いずれかの引数が null の場合IllegalArgumentException
- test
が boolean を返さない場合、または (test
の戻り値の型を変更してターゲットの型と一致させても) 3 つのすべてのメソッド型が一致しない場合public static MethodHandle catchException(MethodHandle target, Class<? extends Throwable> exType, MethodHandle handler)
ターゲットとハンドラの対応する引数と戻り値の型は基本的に同じである必要がありますが、ハンドラでは (guardWithTest
の述語と同様に) 末尾の複数の引数を省略できます。さらにハンドラは、exType
またはスーパータイプの先頭のパラメータを追加で 1 つ持つ必要があります。
結果となるアダプタの擬似コードを次に示します。
保存された引数 (擬似コードでは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
- 一致する例外がスローされた場合に呼び出すメソッドハンドルNullPointerException
- いずれかの引数が null の場合IllegalArgumentException
- handler
が指定された例外の型を受け入れない場合、またはメソッドハンドルの型に含まれる戻り値の型と対応するパラメータが一致しない場合public static MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType)
exType
の例外をスローするメソッドハンドルを生成します。メソッドハンドルは、exType
の単一の引数を受け入れ、それを即時に例外としてスローします。メソッド型では形式上、returnType
の戻り値が指定されます。戻り値の型は、どのようなものでもかまいません。メソッドハンドルが通常どおりに戻ることは決してないので、メソッドハンドルの動作には何の影響もありません。NullPointerException
- どちらかの引数が null の場合 バグまたは機能を送信
詳細な API リファレンスおよび開発者ドキュメントについては、Java SE のドキュメントを参照してください。そのドキュメントには、概念的な概要、用語の定義、回避方法、有効なコード例などの、開発者を対象にしたより詳細な説明が含まれています。
Copyright © 1993, 2013, Oracle and/or its affiliates. All rights reserved.