2012-02-17 17 views
3

私には数多くの機能があり、互いの選択肢があります。彼らは入力を取り、出力を返しますが、どちらの場合も出力は少し異なります。それらはすべて単一のラッパークラスに組み込まれています。非静的メソッドを動的に呼び出す

メソッド名を文字列として渡して呼び出したいと思います。私はまた、if文、手動で不要の膨大なリストを維持避けたい:

if(methodName.equals("method1") 
    return method1(argument); 
... 
else if(methodName.equals("method176") 
    return method176(argument); 

は、これまでのところ私は、動的にメソッドを呼び出す方法を考え出したが、メソッドは静的である場合のみ:

try { 
    method = MyMainClass.class.getDeclaredMethod(methodName, MyArgumentClass.class); 
    ResultClass result = (ResultClass)method.invoke(null, myArgument); 
    return result; 
} 
catch(Exception e) 
{ 
    e.printStackTrace(); 
    System.exit(1); 
    return null; 
} 

非静的メソッドの場合はこれを実行できますか?静的クラスの代わりにクラスインスタンスの関数を呼び出しますか?

+1

答えはありませんが、技術的には反射を使用することは可能性はありません。コンパイル・タイプのチェックを失い、コード解析(IDE内の呼び出し階層など)が難しくなり、メソッドの名前を変更するには文字列を変更する必要があります。ストラテジーパターンのような別の方法を検討したり、メソッドの数を減らしてパラメーターをパラメータ化することをお勧めします。 – sleske

答えて

4

はいを​​見てください。 Java reflectionを使用すると、invokeメソッドの最初の引数としてインスタンスを渡すだけです。

読む:http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Method.html#invoke

try { 
    MyArgumentClass argument = new MyArgumentClass(); 
    MyMainClass instance = new MyMainClass(argument); 
    method = MyMainClass.class.getDeclaredMethod(methodName, MyArgumentClass.class); 
    ResultClass result = (ResultClass) method.invoke(instance, myArgument); 
    return result; 
} 
catch(Exception e) 
{ 
    e.printStackTrace(); 
    System.exit(1); 
    return null; 
} 

他の回答で指摘したように、これはあなたの問題への最善のアプローチではありません。

interface MyOperation{ 
    public ResultClass execute(MyArgumentClass argument); 
} 

public class Method1 implements MyOperation { 
    public ResultClass execute(MyArgumentClass argument){ 
     .... 
    } 
} 

public class Method176 implements MyOperation { 
    public ResultClass execute(MyArgumentClass argument){ 
     .... 
    } 
} 

public class DoIt{ 
    public ResultClass doIt(MyOperation method, MyArgumentClass argument){ 
     return method.doIt(argument); 
    } 
} 
+0

ありがとう、それは私が探していたものです。 – Marek

5

可能であれば、反射を避けることをお勧めします。あなたの問題は、Strategy patternを使ってより良いデザインで解決できるようです。

+0

+1反射を使用することは技術的に可能ですが、おそらく良い考えではありません。 – sleske

+0

Wikipediaの例によると、これはあまり変わっていないようです。私はString引数として "戦略"を渡したいので、私はまだif文の巨大なリストで終わります:if(strategy.equals( "add"))context = new Context(new ConcreteStrategyAdd()); if(strategy.equals( "subtract"))context =新しいコンテキスト(新しいConcreteStrategySubtract()); ... – Marek

+0

これにはMap を利用できます。 –

1

はい、可能です。メソッドを呼び出すオブジェクトをinvoke呼び出しの最初の引数として渡します。オブジェクトを使用するには、オブジェクトのgetClassを呼び出します。

1

あなたのやっているようにクラスから取得されたメソッドのインスタンスを取得し、メソッドを呼び出すクラスのインスタンスでMethod.invoke()を呼び出します。

Springから入手できるいくつかの豆を使って、そのルートに興味があれば、同様のことを達成することもできます。

関連する問題