4

以下を私の問題のクラスにしましょう:

class MyClass {
    String name() {
        return toString();
    }
}

MethodType「任意の」オブジェクトを返すメソッドを記述するインスタンスを作成したいと考えています。私は次のことを試みています:

MethodType genericTypeWithObjectReturn = 
    MethodType.methodType(Object.class, new Class[] {});

次に、を使用して方法を見つけようとします

MethodHandle mh = 
    lookup.findVirtual(MyClass.class, "name", genericTypeWithObjectReturn);

上記の行を使用すると、例外が発生します。

Caused by: java.lang.NoSuchMethodError: MyClass.name()Ljava/lang/Object;

私の観察では、メソッドの戻り値の型はまったく同じ型でなければなりません。つまりString.class、上記のステートメントで定義するために使用する必要がありましたMethodType。これは正しいです?私が説明した方法でこれを行うことができ、できればリフレクション API を使用しない方法はありますか?

4

3 に答える 3

2

答えがまだ見つからないので...

MethodType は正確でなければなりません。これは MethodHandles-API の大きな問題点ですが、変換を制御することによって最適化が可能になります。解決策は、リフレクションを使用してメソッドを見つけてから、MethodHandles#unreflect* を使用してハンドルを取得することです。

于 2014-03-11T10:33:10.317 に答える
0

はい。正しいメソッド タイプを解決するには、String.class を使用する必要があります。メソッドハンドルAPIで実装できないことはわかっていますが、Reflection APIを使用できます。

于 2015-07-18T15:14:37.727 に答える
0

戻り値の型を含む正確なメソッド型を指定せずに、メソッドを使用してfind{Virtual,Static}メソッド ハンドルを取得する方法はありません。これは、Java プログラミング言語では許可されていませんが、JVM では戻り値の型のオーバーロードが許可されているためです。Class.getMethodのドキュメントから(強調鉱山):

クラスまたはインターフェイス C で一致するメソッドを見つけるには: C が、指定された名前とまったく同じ仮パラメーター型を持つパブリック メソッドを 1 つだけ宣言する場合、それが反映されたメソッドです。そのようなメソッドが C に複数あり、これらのメソッドの 1 つが他のどのメソッドよりも具体的な戻り値の型を持っている場合、そのメソッドが反映されます。それ以外の場合は、いずれかの方法が任意に選択されます。

クラスに複数の一致するメソッドが存在する可能性があることに注意してください。これは、Java 言語ではクラスが同じシグネチャで異なる戻り値の型を持つ複数のメソッドを宣言することを禁止しているのに対し、Java 仮想マシンでは禁止されていないためです。この仮想マシンの柔軟性の向上は、さまざまな言語機能の実装に使用できます。たとえば、共変リターンはブリッジ メソッドで実装できます。ブリッジ メソッドとオーバーライドされるメソッドのシグネチャは同じですが、戻り値の型は異なります。

したがって、JVM メソッドは、同じ署名を持つが異なる (より具体的ではない) 戻り値の型を持つ他のメソッドが存在することによって、Class.getMethod からアクセスできなくなる可能性があります。メソッド ハンドルの目的は、ソース内の戻り値の型のオーバーロードをサポートする言語や、JVM へのマッピングの一部として戻り値の型のオーバーロードを生成する言語など、JVM で他の言語をサポートすることであるため、この穴を修正する必要がありました。指定する正確なタイプ。(int、long、および BigInteger を返すオーバーロードを含むメソッドを想像できます。pow(int, int)これらは、 のコンテキスト タイプに基づいてソース言語によって選択されfoo(pow(1000, 100000));ます。)

すべてのメソッドにアクセスできるようにするという厳しい要件は別として、API 設計の観点からは、目的のメソッドが見つからない場合は、引数に互換性があるが異なるメソッドを黙って選択するよりも、すばやく失敗する方が間違いなく優れています。


Class.getMethod のルックアップ セマンティクスに満足している場合は、それを使用して、返されたメソッドでMethodHandles.Lookup.unreflectを呼び出すことができます。

于 2014-06-29T05:58:17.497 に答える