2011-05-16 11 views
15

私はインタプリタを使ってコードを動的に呼び出す作業をしていますが、JLS section 15.12で説明したように、メソッド解決のスティッキーな醜い領域に入り込んでいます。Java:ランタイムメソッドの解像度

メソッドを選択する「簡単な」方法は、すべての引数の正確な型を知っているときです。その時点で、Class.getDeclaredMethod(String name, Class[] parameterTypes)を使用できます。メソッドのアクセシビリティとクラスのスーパークラス/スーパーインタフェースをチェックする必要があるかもしれません。

しかし、これは次のいずれかの場合、それは一種の無用ですので、カバーしていない:

  • ボクシング/アンボクシングプリミティブ
  • サブタイプ
  • 可変引数
  • することができnull引数を(インタプリタが別のことを知っていない限り、コンパイル時には、クラス/インタフェースにnullをキャストすることによって曖昧さがなくなります)
  • プリミティブ型変換(Javaの一部ではありませんが、言語の文脈 - 例:すべての数値は、浮動小数点であるため、Javaコードはintを取るかもしれないが、発信者がint又はdoubleのいずれかである数に通過ライノのJavascript)

(最初の簡単な例については以下を参照だから今、私は私自身のメソッド解決ライブラリを記述する必要が3)

...

は、このを支援する任意の周知のフレームワークライブラリはありますか?

package com.example.test.reflect; 

import java.lang.reflect.Method; 

public class MethodResolutionTest { 
    public void compute(int i)    { /* implementation... */ } 
    public void compute(Long l)    { /* implementation... */ } 
    public void compute(Object obj)   { /* implementation... */ } 
    public void compute(String... strings) { /* implementation... */ } 

    public static void main(String[] args) { 
     Class<?> cl = MethodResolutionTest.class; 

     /* these succeed */ 
     findAndPrintMethod(cl, "compute", int.class); 
     findAndPrintMethod(cl, "compute", Long.class); 
     findAndPrintMethod(cl, "compute", Object.class); 
     findAndPrintMethod(cl, "compute", String[].class); 

     /* these fail */ 
     findAndPrintMethod(cl, "compute", Integer.class); 
     findAndPrintMethod(cl, "compute", long.class); 
     findAndPrintMethod(cl, "compute", MethodResolutionTest.class); 
     findAndPrintMethod(cl, "compute", String.class, String.class); 
    } 
    private static void findAndPrintMethod(Class<?> objectClass, 
      String methodName, Class<?>... parameterTypes) 
    { 
     try { 
      Method method = findMethod(objectClass, methodName, 
        parameterTypes); 
      System.out.println(method.toString()); 
     } 
     catch (SecurityException e) { 
      e.printStackTrace(); 
     } 
     catch (NoSuchMethodException e) { 
      e.printStackTrace(); 
     } 
    } 
    private static Method findMethod(Class<?> objectClass, 
      String methodName, Class<?>[] parameterTypes) 
     throws SecurityException, NoSuchMethodException 
    { 
     return objectClass.getDeclaredMethod(methodName, parameterTypes); 
    } 
} 
+1

[この回答は、サブタイプのようないくつかのケースを処理します](http://stackoverflow.com/questions/2580665/java-getmethod-with-superclass-parameters-in-method/2580699#2580699)。 –

+1

@Jonathon:私はisAssignableFromについて知っています。私はサブタイプとボクシング/アンボクシングで仕事をしている自家製のものを手に入れました。それから、私は変動を始め、それは不快になりました、そして、私は考えました。「ちょっと待って、どうして私はこれをやっているの?私は特に既存のライブラリを探しています。 (または、少なくとも既存のテストケースの良いセット)それ以外の場合は、私自身でこれを行うことができますが、それは大きな苦痛です。 –

+1

あなたが甘い図書館を見つけられない限り、私はあなたがしていることは、醜く読むのが難しいと思っています。 –

答えて

-1

私はMVELとプロパティを持ついくつかの成功を収めてきましたが、私はそれはメソッド呼び出しをディスパッチできるかどうかを思い出すことができません。

しかし、あなたは完全に別の言語を探しているかもしれません。問題の性質を考えれば、Javaと非常にきれいに統合されたGroovyを見てみることをお勧めします。

+0

ええと、私はさまざまな理由でJavaに「固執」しています。最大のものはメンテナンス性です(別の言語を追加すると、他の開発者から助けを得る能力が大幅に制限されます) –

2

コモンズ々BeanUtilsは、一致する方法を見つけるために、この機能を持っている: getMatchingAccessibleMethod

それはプリミティブ型で動作しますが、ドキュメントが言うように、それはやや決定不能です。

+1

'getMatchingAccessibleMethod'では、パラメータ 'Long.class'は' foo(long) 'にマッチしますが、' Long.TYPE'は 'foo(Long)'にマッチしません。 – McDowell

+0

+1:@Bengt:Apacheのツールがいくつかあります。私が望んでいたが、少なくとも何か。 –

3

this blog postを読んで、ClassMateをチェックしてください。あなたのために大部分の仕事をするはずです。

+0

ARGH!有望ですが、わずかに異なります - ジェネリック型を解決しますが、メソッドの解決には何もしません。しかし、少なくともそれはスタートであり、私はそれを拡張するために著者に助力を与えることができると確信しています。 –

0

guava-discussのユーザーの1人が、Mirror libraryをご覧ください。

残念ながら、少なくとも現在は、オーバーロードの解決を扱っていません。