public final class LambdaMetafactory extends Object
おそらく型適応と引数の部分評価の後に、指定されたMethodHandleへの委譲によって、1つ以上のインタフェースを実装する単純な関数オブジェクトの作成を容易にするメソッド。 これらのメソッドは一般に、invokedynamicコール・サイトのブートストラップ・メソッドとして使用され、Javaプログラミング言語のラムダ式およびメソッド参照式機能をサポートします。
提供されたMethodHandleによって指定された動作への間接アクセスは、3つのフェーズで順番に進行します。
- リンケージ。このクラスのメソッドが呼び出されたときに発生します。 これらは引数として、実装されるインタフェース(一般的に関数型インタフェース、単一抽象メソッドを持つもの)、実装されるそのインタフェースからのメソッドの名前とシグネチャ、そのメソッドに求められる実装動作を記述するメソッド・ハンドルを取り(他の追加メタデータを取ることもある)、ターゲットを適切な関数オブジェクトを作成するために使用できる
CallSiteを生成します。 リンケージでは、ターゲット・インタフェースを実装する新しいクラスが動的にロードされることもあります。CallSiteは関数オブジェクトのファクトリと見なすことができるため、これらのリンケージ・メソッドはメタファクトリと呼ばれます。 - キャプチャ。
CallSiteのターゲットが呼び出されるときに発生し(一般的にinvokedynamicコール・サイトによって)、関数オブジェクトを生成します。 これは、単一ファクトリCallSiteに対して何度も発生する場合があります。 キャプチャでは、新しい関数オブジェクトが割り当てられたり、既存の関数オブジェクトを返したりすることもあります。 動作MethodHandleには、指定されたインタフェース・メソッドのパラメータ以外に追加パラメータが指定される場合があります。これらはキャプチャ・パラメータと呼ばれ、CallSiteターゲットへの引数として指定される必要があり、動作MethodHandleに早期バインドされる場合があります。 キャプチャ・パラメータの数および型はリンケージ中に決定されます。CallSiteターゲットの呼出しにより生成された関数オブジェクトのアイデンティティは予測できないため、アイデンティティに依存する操作(参照の等価性、オブジェクトのロック、System.identityHashCode()など)は、異なる実装や同じ実装での異なる呼出し時に生成される可能性があります。 - 呼出し。実装されたインタフェース・メソッドが関数オブジェクトで呼び出されたときに発生します。 これは、単一関数オブジェクトに対して何度も発生する場合があります。 動作
MethodHandleによって参照されるメソッドは、MethodHandle.invoke(Object...)による場合と同様に、キャプチャ引数と呼出しで指定される追加引数を使用して呼び出されます。
呼出しで許可される入力または結果のセットを制限することが便利な場合があります。 たとえば、ジェネリック・インタフェースPredicate<T>がPredicate<String>としてパラメータ化されるときは、入力はStringである必要があります(実装するメソッドが任意のObjectを許可していても)。 リンケージで、追加のMethodTypeパラメータがインスタンス化されたメソッド型を記述するとします。すると呼出しで、引数と最終的な結果がこのMethodTypeに基づいてチェックされます。
このクラスは2つの形式のリンケージ・メソッドを提供します。最適化されたプロトコルを使用する標準版(metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType))と、代替版(altMetafactory(MethodHandles.Lookup, String, MethodType, Object...))です。 代替版は標準版の一般化したもので、フラグおよび追加引数を介して生成された関数オブジェクトの動作に対する追加制御を提供します。 代替版では、関数オブジェクトの次の属性を管理する機能が追加されます。
- ブリッジング。 引数または戻り型の適応を含む、メソッド・シグネチャの複数のバリエーションを実装するのに役立つ場合があります。 これは、メソッドの複数の異なるVMシグネチャが、言語によって論理的に同じメソッドであると見なされるときに発生します。 フラグ
FLAG_BRIDGESは、追加のMethodTypeのリストが提供されることを示します(それぞれが結果の関数オブジェクトによって実装される)。 これらのメソッドは同じ名前およびインスタンス化された型を共有します。 - 複数のインタフェース。 必要に応じて、関数オブジェクトは複数のインタフェースを実装できます。 (これらの追加インタフェースは一般的に、メソッドなしのマーカー・インタフェースです。) フラグ
FLAG_MARKERSは、追加インタフェースのリストが提供されることを示します(それぞれが結果の関数オブジェクトによって実装される)。 - 直列化可能性。 生成された関数オブジェクトは一般的に直列化をサポートしません。 必要に応じて、関数オブジェクトが直列化可能であるべきことを示すために
FLAG_SERIALIZABLEを使用できます。 直列化可能関数オブジェクトは、キャプチャ・クラス(MethodHandles.Lookupのパラメータcallerによって記述されるクラス)からの追加支援を必要とする、SerializedLambdaクラスのインスタンスを、直列化形式として使用します。詳細は、SerializedLambdaを参照してください。
リンケージ引数は次のことを前提とします。
invokedType(CallSiteシグネチャを記述)は、型(D1..Dk)および戻り型RdのKパラメータを持つ。samMethodType(実装されたメソッド型を記述)は、型(U1..Un)および戻り型RuのNパラメータを持つ。implMethod(実装を提供するMethodHandle)は、型(A1..Am)および戻り型RaのMパラメータを持つ(メソッドがインスタンス・メソッドを記述する場合、このメソッド・ハンドルのメソッド型はレシーバに対応する追加の最初の引数をすでに含む)。instantiatedMethodType(呼出しでの制限を許可)は、型(T1..Tn)および戻り型RtのNパラメータを持つ。
さらに、次のリンケージ不変条件を保持する必要があります。
- Rdがインタフェース
implMethodが直接メソッド・ハンドルsamMethodTypeおよびinstantiatedMethodTypeが同じ引数カウントNを持つ、およびi=1..Nの場合にTiおよびUiが同じ型、またはTiおよびUiが両方とも参照型かつTiがUiのサブタイプ- RtおよびRuが同じ型、または両方が参照型かつRtがRuのサブタイプ
- K + N = M
- i=1..Kの場合、Di = Ai
- i=1..Nの場合、TiはAjに適応可能、j=i+k
- 戻り型Rtがvoid、または戻り型RaがvoidでなくRtに適応可能
さらに、キャプチャ時は、implMethodがインスタンス・メソッドに対応し、キャプチャ引数(K > 0)が存在し、最初のキャプチャ引数(レシーバに対応する)は非nullである必要があります。
次のように型QはSに適応可能と見なされます。
| Q | S | リンク時チェック | 呼出し時チェック |
|---|---|---|---|
| プリミティブ | プリミティブ | Qはプリミティブ・ワイドニング変換でSに変換可能 | なし |
| プリミティブ | 参照 | SはWrapper(Q)のスーパータイプ | Wrapper(Q)からSにキャスト |
| 参照 | プリミティブ | パラメータ型の場合: Qはプリミティブ・ラッパー、Primitive(Q)はSにワイドニング可能 戻り型の場合: Qがプリミティブ・ラッパーの場合はPrimitive(Q)がSにワイドニング可能かをチェック |
Qがプリミティブ・ラッパーでない場合、Qを基底Wrapper(S)にキャスト。たとえば、数値型の場合はNumber |
| 参照 | 参照 | for parameter types: S is a supertype of Q for return types:なし |
QからSにキャスト |
- APIの注:
- これらのリンケージ・メソッドはJava言語のラムダ式およびメソッド参照の評価をサポートするように設計されています。 ソース・コード内のすべてのラムダ式またはメソッド参照に、関数型インタフェースであるターゲット型が存在します。 ラムダ式を評価することで、そのターゲット型のオブジェクトが生成されます。 ラムダ式の評価で推奨されるメカニズムは、メソッドのラムダ本文を脱糖し、invokedynamicコール・サイト(静的引数リストが関数型インタフェースの唯一のメソッドおよび脱糖された実装メソッドを記述し、ターゲット型を実装するオブジェクト(ラムダ・オブジェクト)を返す)を呼び出すことです。 (メソッド参照の場合、実装メソッドは単に参照されるメソッドです、脱糖は必要ありません。)
実装メソッドの引数リストとインタフェース・メソッドの引数リストはいくつかの点で異なる場合があります。 実装メソッドは、ラムダ式によってキャプチャされる引数に対応するために追加引数を持つ場合があります。引数に許可された適応(キャスト、ボクシング、アンボクシング、プリミティブ・ワイドニングなど)による違いがある場合もあります。 (可変引数適応はメタファクトリによって扱われません。これらは呼出し元によって扱われることが期待されます。)
invokedynamicコール・サイトには2つの引数リスト、静的引数リストと動的引数リストがあります。 静的引数リストは定数プールに格納されますが、動的引数はキャプチャ時にオペランド・スタックにプッシュされます。 ブートストラップ・メソッドは、静的引数リスト全体(この場合、実装メソッド、ターゲット・インタフェースおよびターゲット・インタフェース・メソッドを記述する情報を含む)、動的引数の数と静的な型(ただし値ではない)およびinvokedynamicサイトの静的な戻り型を記述するメソッド・シグネチャにアクセスできます。
- 実装上の注意:
- 実装メソッドはメソッド・ハンドルで記述されます。 理論上は、任意のメソッド・ハンドルを使用できます。 ただし、現在サポートされているのは、仮想、インタフェース、コンストラクタおよび静的メソッドの呼出しを表す直接メソッド・ハンドルです。
- 導入されたバージョン:
- 1.8
-
フィールドのサマリー
フィールド 修飾子と型 フィールド 説明 static intFLAG_BRIDGESラムダ・オブジェクトが追加のブリッジ・メソッドを必要としていることを示す、代替メタファクトリ用のフラグstatic intFLAG_MARKERSラムダ・オブジェクトがSerializable以外に他のマーカー・インタフェースを実装することを示す、代替メタファクトリ用のフラグstatic intFLAG_SERIALIZABLEラムダ・オブジェクトが直列化可能である必要があることを示す、代替メタファクトリ用のフラグ -
メソッドのサマリー
修飾子と型 メソッド 説明 static CallSitealtMetafactory(MethodHandles.Lookup caller, String invokedName, MethodType invokedType, Object... args)適切な型適応および引数の部分評価の後、指定されたMethodHandleへの委譲により、1つ以上のインタフェースを実装する単純な関数オブジェクトの作成を容易にします。static CallSitemetafactory(MethodHandles.Lookup caller, String invokedName, MethodType invokedType, MethodType samMethodType, MethodHandle implMethod, MethodType instantiatedMethodType)適切な型適応および引数の部分評価の後、指定されたMethodHandleへの委譲により、1つ以上のインタフェースを実装する単純な関数オブジェクトの作成を容易にします。
-
フィールド詳細
-
FLAG_SERIALIZABLE
public static final int FLAG_SERIALIZABLEラムダ・オブジェクトが直列化可能である必要があることを示す、代替メタファクトリ用のフラグ- 関連項目:
- 定数フィールド値
-
FLAG_MARKERS
public static final int FLAG_MARKERSラムダ・オブジェクトがSerializable以外に他のマーカー・インタフェースを実装することを示す、代替メタファクトリ用のフラグ- 関連項目:
- 定数フィールド値
-
FLAG_BRIDGES
public static final int FLAG_BRIDGESラムダ・オブジェクトが追加のブリッジ・メソッドを必要としていることを示す、代替メタファクトリ用のフラグ- 関連項目:
- 定数フィールド値
-
-
メソッドの詳細
-
metafactory
public static CallSite metafactory(MethodHandles.Lookup caller, String invokedName, MethodType invokedType, MethodType samMethodType, MethodHandle implMethod, MethodType instantiatedMethodType) throws LambdaConversionException適切な型適応および引数の部分評価の後、指定されたMethodHandleへの委譲により、1つ以上のインタフェースを実装する単純な関数オブジェクトの作成を容易にします。 一般的にinvokedynamicコール・サイトのブートストラップ・メソッドとして、Javaプログラミング言語のラムダ式およびメソッド参照式機能をサポートするために使用されます。これは標準の、合理化されたメタファクトリです。
altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)によってより高い柔軟性が提供されます。 このメソッドの動作の概要はすでに説明済です。このメソッドから返される
CallSiteのターゲットが呼び出されると、結果の関数オブジェクトは、invokedTypeの戻り型で指定されるインタフェースを実装し、かつinvokedNameで指定される名前とsamMethodTypeで指定されるシグネチャを持つメソッドを宣言する、クラスのインスタンスです。Objectからの追加メソッドをオーバーライドすることもできます。- パラメータ:
caller- 呼出し元のアクセス可能性権限を持つルックアップ・コンテキストを表します。 具体的には、ルックアップ・コンテキストには「プライベート・アクセス」特権が必要です。invokedynamicで使用されるときは、これはVMによって自動的にスタックされます。invokedName- 実装するメソッドの名前。invokedynamicで使用されるときは、これはInvokeDynamic構造のNameAndTypeによって提供され、VMによって自動的にスタックされます。invokedType-CallSiteの期待されるシグネチャ。 パラメータ型はキャプチャ変数の型を表し、戻り型は実装するインタフェースです。invokedynamicで使用されるときは、これはInvokeDynamic構造のNameAndTypeによって提供され、VMによって自動的にスタックされます。 実装メソッドがインスタンス・メソッドで、このシグネチャがパラメータを持つ場合は、呼出しシグネチャの最初のパラメータはレシーバに対応する必要があります。samMethodType- 関数オブジェクトによって実装されるメソッドのシグネチャおよび戻り型。implMethod- 呼出しで(引数型および戻り型が適切に適応され、キャプチャ引数に呼出し引数が付加された状態で)呼び出される実装メソッドを記述する直接メソッド・ハンドル。instantiatedMethodType- 呼出しで動的に適用されるシグネチャおよび戻り型。 これは、samMethodTypeと同じ場合、またはその特殊化の場合があります。- 戻り値:
- CallSite。そのターゲットを使用してキャプチャを実行し、
invokedTypeで指定されるインタフェースのインスタンスを生成できる - 例外:
LambdaConversionException-aboveで説明されているリンケージ不変条件のいずれかに違反がある場合、またはルックアップ・コンテキストにプライベート・アクセス権限がない場合。
-
altMetafactory
public static CallSite altMetafactory(MethodHandles.Lookup caller, String invokedName, MethodType invokedType, Object... args) throws LambdaConversionException適切な型適応および引数の部分評価の後、指定されたMethodHandleへの委譲により、1つ以上のインタフェースを実装する単純な関数オブジェクトの作成を容易にします。 一般的にinvokedynamicコール・サイトのブートストラップ・メソッドとして、Javaプログラミング言語のラムダ式およびメソッド参照式機能をサポートするために使用されます。これは一般的で、柔軟性の高いメタファクトリです。合理化されたバージョンが
metafactory(java.lang.invoke.MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)によって提供されます。 このメソッドの動作の概要はすでに説明済です。このメソッドの引数リストには3つの固定パラメータが含まれ、
invokedynamic呼出しでブートストラップ・メソッドのためにVMによって自動的にスタックされるパラメータと、追加パラメータを含むObject[]パラメータに対応しています。 このメソッドに宣言される引数リストは次のとおりです。CallSite altMetafactory(MethodHandles.Lookup caller, String invokedName, MethodType invokedType, Object... args)しかし、引数リストが以下であるかのように動作します。
CallSite altMetafactory(MethodHandles.Lookup caller, String invokedName, MethodType invokedType, MethodType samMethodType, MethodHandle implMethod, MethodType instantiatedMethodType, int flags, int markerInterfaceCount, // IF flags has MARKERS set Class... markerInterfaces, // IF flags has MARKERS set int bridgeCount, // IF flags has BRIDGES set MethodType... bridges // IF flags has BRIDGES set )metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)の引数リスト内の引数は、そのメソッド内と同じ仕様を持ちます。 追加引数は次のように解釈されます。flagsは追加オプションを示します。これは、必要なフラグのビット単位ORです。 定義済フラグはFLAG_BRIDGES、FLAG_MARKERSおよびFLAG_SERIALIZABLEです。markerInterfaceCountは関数オブジェクトが実装する追加インタフェースの数で、FLAG_MARKERSフラグが設定されている場合にのみ存在します。markerInterfacesは実装する追加インタフェースの可変長リストで、その長さはmarkerInterfaceCountと等しく、FLAG_MARKERSフラグが設定されている場合にのみ存在します。bridgeCountは関数オブジェクトが実装する追加メソッド・シグネチャの数で、FLAG_BRIDGESフラグが設定されている場合にのみ存在します。bridgesは実装する追加メソッド・シグネチャの可変長リストで、その長さはbridgeCountと等しく、FLAG_BRIDGESフラグが設定されている場合にのみ存在します。
markerInterfacesで指定される各クラスには、前述のinvokedTypeの戻り型、Rdと同じ制限が適用されます。bridgesで指定される各MethodTypeには、前述のsamMethodTypeと同じ制限が適用されます。flagsにFLAG_SERIALIZABLEが設定されているとき、関数オブジェクトはSerializableを実装し、適切なSerializedLambdaを返すwriteReplaceメソッドを持ちます。callerクラスは、SerializedLambdaで説明したとおり適切な$deserializeLambda$メソッドを持つ必要があります。このメソッドから返される
CallSiteのターゲットが呼び出されるとき、結果の関数オブジェクトは次のプロパティを持つクラスのインスタンスです。- このクラスは
invokedTypeの戻り型で指定されるインタフェースと、markerInterfacesで指定されるインタフェースを実装します。 - このクラスは
invokedNameで指定される名前、samMethodTypeで指定されるシグネチャ、およびbridgesで指定される追加シグネチャでメソッドを宣言します。 - このクラスは
Objectからのメソッドをオーバーライドでき、直列化に関連するメソッドを実装できます。
- パラメータ:
caller- 呼出し元のアクセス可能性権限を持つルックアップ・コンテキストを表します。 具体的には、ルックアップ・コンテキストには「プライベート・アクセス」特権が必要です。invokedynamicで使用されるときは、これはVMによって自動的にスタックされます。invokedName- 実装するメソッドの名前。invokedynamicで使用されるときは、これはInvokeDynamic構造のNameAndTypeによって提供され、VMによって自動的にスタックされます。invokedType-CallSiteの期待されるシグネチャ。 パラメータ型はキャプチャ変数の型を表し、戻り型は実装するインタフェースです。invokedynamicで使用されるときは、これはInvokeDynamic構造のNameAndTypeによって提供され、VMによって自動的にスタックされます。 実装メソッドがインスタンス・メソッドで、このシグネチャがパラメータを持つ場合は、呼出しシグネチャの最初のパラメータはレシーバに対応する必要があります。args- 前述のaltMetafactory(MethodHandles.Lookup, String, MethodType, Object...)の説明のとおり、必要な引数samMethodType、implMethod、instantiatedMethodTypeおよびflagsとオプション引数を含むObject[]配列- 戻り値:
- CallSite。そのターゲットを使用してキャプチャを実行し、
invokedTypeで指定されるインタフェースのインスタンスを生成できる - 例外:
LambdaConversionException-aboveで説明されているリンケージ不変条件のいずれかに違反がある場合、またはルックアップ・コンテキストにプライベート・アクセス権限がない場合。
-