2016-10-09 4 views
1

私は配列の引数の中から選択して特定のものを返すメソッドを持っています。例えば、ここでその方法は:引数渡しのメソッド/関数を含む配列

private <T> T selectOnType(T[] selection, T defaultOp){ 
    switch(this.type){ 
     case Resources.TEXT: 
      return selection[Resources.TEXT]; 
     case Resources.LISTEN: 
      return selection[Resources.LISTEN]; 
     default: 
      return defaultOp; 
    } 
} 

どのように上記のこの方法にその配列を渡すことができるようにするために方法参照(すなわち、関数ポインタ)の完全な配列を構築することができますか?

は、私はそのようなことをやってみました:

java.util.function.Function<Void, Void>[] array = {ClassA::method1, ClassA::method2}; 

(法1とmethod1には、引数を取りませんし、voidを返す場合)

をしかし、それは言ってコンパイラエラーがスローされます。

互換性のない型:無効なメソッド参照ですが、引数は不要です。        
が見つかりました:
       理由をがjava.lang.Void:実際の仮引数リストの長さが異なる

私は、次のようなラムダで遊んでされています:

() -> ClassA.method1() 

しかし、私はそれを働かせることができませんでした。誰もが私が間違ってやっていることを知っているとこの問題の解決策を知っていますか?

EDIT: 私はスタックオーバーフローthisを見てきましたが、これは、C#のためであると私はJavaでそれを模倣する方法を考え出したていません。

例:

public class Word{ 
    private final String text; 
    private int listenCorrect = 0, textCorrect = 0; 
    public Word(final String test){ 
     this.text = text; 
    } 
    public void incListenCorrect(){ 
     listenCorrect++; 
    } 
    public void incTextCorrect(){ 
     textCorrect--; 
    } 
} 

そして最後に、私はMainクラスを持っている:
のは、私がWordクラスがあるとしましょう。

public class Main{ 
    int type = 0; 
    public void action(){ 
     Word word = new Word("Hello"); 
     // 'Functions' is used to represent something I tried above (just for demonstration) 
     Function[] array = {word::incListenCorrect, word::incTextCorrect}; 
     Function picked = selectOnType(array, word::incTextCorrect); 
     picked.call(); 
    } 
    /* 
    * Resources is another class that contains the following values: 
    *   public static final int TEXT  = 0; 
    *   public static final int LISTEN  = 1; 
    */ 
    private <T> T selectOnType(T[] selection, T defaultOp){ 
     switch(this.type){ 
      case Resources.TEXT: 
       return selection[Resources.TEXT]; 
      case Resources.LISTEN: 
       return selection[Resources.LISTEN]; 
      default: 
       return defaultOp; 
     } 
    } 
} 
+1

'method1'と' method2'インスタンスメソッドまたは静的メソッドはありますか? – ajb

+0

あなたのメソッドは 'Function 'と同じではなく、 'Runnable'になります – njzk2

+0

@ajb私が含まれている例を見てください。それらはインスタンスメソッドです。 –

答えて

3

Function:私は(下記参照)typeはどちらかlistentextある場合は、それらの間で選択するために、その中にこれらの2つの方法で配列を持ちたい(Mainクラス)actionメソッド内1つの引数をとり、結果を返すメソッドです。引数を取らず結果を返さないメソッドを使用しています。これにはFunctionを使用することはできません(Voidはこれを回避する方法ではありません)。the java.util.functionパッケージには、さまざまな共通の組み合わせ(引数を取らずに結果を返すメソッド、 2つの引数と結果を返さないメソッド、プリミティブな引数を取るメソッド、または型がクラスの型などでないためFunctionで機能しないプリミティブな結果を返すメソッド)。

は、引数なしなし結果との機能的なインターフェイスのためのjava.util.functionでクラスはありませんが、Runnableはそのために使用することができます。

正しいインターフェイスを使用していることを確認する必要があります。

注:彼らは任意の引数、インスタンスメソッドが取ることさえ隠された「インスタンス」引数を取らないように私はmethod1method2を想定したが、静的メソッドです。それらがインスタンスメソッドである場合は、処理が異なる必要があります。

ここでは、それらがインスタンスメソッドであることを明確にしたので、状況は異なりますが、メソッドの取得方法によって異なります。あなたが言うならば、あなたがクラス名を使用しているので、あなたは引数としてインスタンスを提供する必要があります。

Word::incListenCorrect 

そのため、Word::incListenCorrectは、.accept()でメソッドを呼び出すときに、Consumer<Word>のような1つの引数を取るメソッドの機能インタフェースを返し、引数としてWordを渡す必要があります。 しかし

word::incListenCorrect 

は非常に異なっています。さて、wordインスタンスはメソッドリファレンスに "baked"されるので、引数として渡す必要はありません。したがって、この場合でも引数を取らずに値を返さないインターフェイスが必要です(Runnable)。あなたは

Runnable r = word::incListenCorrect;  
r.run(); 

を言うときrRunnableある場合、それは自動的にあなたがそれをメソッド参照を割り当てたときwordrの一部となっているため、インスタンスメソッドのインスタンスとしてwordを使用します。

+0

これを見ていきます。また、私が行っていることをさらに明確にするために追加した例を見てください(つまり、静的メソッドではありません) –

+0

あなた、私の友人は素晴らしいです! :) "x"の引数をとり、結果を返すインスタンスメソッド(上記の例のような)があったら、そのためにlambdasを使用しますか? run()メソッドは引数を取らず、void関数なので、もう 'Runnable'オブジェクトにラップすることはできないと思います。 –

+1

ここで問題となるのは、 'Runnable'、' Consumer '、' Function 'など、正しいタイプが必要なことです。 1つまたは2つの引数がある場合は、 'java.util.function'のインタフェースのうちの1つを使用できます(引数のいくつかがプリミティブ型で、次にできない場合があります)。 3つ以上の引数がある場合は、独自のインターフェイス型を定義し、メソッド参照を使用する必要があります。ラムダは、あなた自身のタイプを定義する必要性を回避する助けにはなりません。 – ajb

関連する問題