356

メソッドを参照渡しする方法を探しています。Java がメソッドをパラメーターとして渡さないことは理解していますが、代替手段を取得したいと考えています。

インターフェースはメソッドをパラメーターとして渡す代わりになると言われましたが、インターフェースが参照によってメソッドとして機能する方法がわかりません。私が正しく理解していれば、インターフェイスは単に定義されていないメソッドの抽象的なセットです。いくつかの異なるメソッドが同じパラメーターで同じメソッドを呼び出す可能性があるため、毎回定義する必要があるインターフェイスを送信したくありません。

私が達成したいのは、これに似たものです:

public void setAllComponents(Component[] myComponentArray, Method myMethod) {
    for (Component leaf : myComponentArray) {
        if (leaf instanceof Container) { //recursive call if Container
            Container node = (Container) leaf;
            setAllComponents(node.getComponents(), myMethod);
        } //end if node
        myMethod(leaf);
    } //end looping through components
}

次のように呼び出されます。

setAllComponents(this.getComponents(), changeColor());
setAllComponents(this.getComponents(), changeSize());
4

17 に答える 17

267

編集:Java 8の時点で、ラムダ式は他の 回答が指摘しているように優れたソリューションです。以下の答えは、Java7以前用に書かれています...


コマンドパターンを見てください。

// NOTE: code not tested, but I believe this is valid java...
public class CommandExample 
{
    public interface Command 
    {
        public void execute(Object data);
    }

    public class PrintCommand implements Command 
    {
        public void execute(Object data) 
        {
            System.out.println(data.toString());
        }    
    }

    public static void callCommand(Command command, Object data) 
    {
        command.execute(data);
    }

    public static void main(String... args) 
    {
        callCommand(new PrintCommand(), "hello world");
    }
}

編集:Pete Kirkhamが指摘しているように、 Visitorを使用してこれを行う別の方法があります。ビジターアプローチはもう少し複雑です-ノードはすべてacceptVisitor()メソッドでビジターを認識する必要があります-しかし、より複雑なオブジェクトグラフをトラバースする必要がある場合は、調べる価値があります。

于 2010-02-02T19:28:09.460 に答える
33

java.lang.reflect.Methodオブジェクトを使用して呼び出しますinvoke

于 2010-02-02T19:25:54.557 に答える
21

まず、パラメーターとして渡したいメソッドを使用してインターフェースを定義します

public interface Callable {
  public void call(int param);
}

メソッドを使用してクラスを実装する

class Test implements Callable {
  public void call(int param) {
    System.out.println( param );
  }
}

//そのように呼び出す

Callable cmd = new Test();

これにより、cmdをパラメーターとして渡し、インターフェースで定義されたメソッド呼び出しを呼び出すことができます。

public invoke( Callable callable ) {
  callable.call( 5 );
}
于 2010-02-02T19:34:26.130 に答える
13

前回チェックしたとき、Javaはあなたが望むことをネイティブに行うことができません。このような制限を回避するには、「回避策」を使用する必要があります。私が見る限り、インターフェースは代替手段ですが、良い代替手段ではありません。おそらく、それが次のような意味であるとあなたに言った人は誰でも:

public interface ComponentMethod {
  public abstract void PerfromMethod(Container c);
}

public class ChangeColor implements ComponentMethod {
  @Override
  public void PerfromMethod(Container c) {
    // do color change stuff
  }
}

public class ChangeSize implements ComponentMethod {
  @Override
  public void PerfromMethod(Container c) {
    // do color change stuff
  }
}

public void setAllComponents(Component[] myComponentArray, ComponentMethod myMethod) {
    for (Component leaf : myComponentArray) {
        if (leaf instanceof Container) { //recursive call if Container
            Container node = (Container) leaf;
            setAllComponents(node.getComponents(), myMethod);
        } //end if node
        myMethod.PerfromMethod(leaf);
    } //end looping through components
}

次に、これを呼び出します。

setAllComponents(this.getComponents(), new ChangeColor());
setAllComponents(this.getComponents(), new ChangeSize());
于 2010-02-02T19:38:19.490 に答える
1

Javaには、名前を渡して呼び出すメカニズムがあります。これは反射メカニズムの一部です。関数は、クラスMethodの追加パラメーターを受け取る必要があります。

public void YouMethod(..... Method methodToCall, Object objWithAllMethodsToBeCalled)
{
...
Object retobj = methodToCall.invoke(objWithAllMethodsToBeCalled, arglist);
...
}
于 2010-02-02T19:47:16.537 に答える
0

オブザーバーパターン(リスナーパターンとも呼ばれる)を使用します。

interface ComponentDelegate {
    void doSomething(Component component);
}

public void setAllComponents(Component[] myComponentArray, ComponentDelegate delegate) {
    // ...
    delegate.doSomething(leaf);
}

setAllComponents(this.getComponents(), new ComponentDelegate() {
                                            void doSomething(Component component) {
                                                changeColor(component); // or do directly what you want
                                            }
                                       });

new ComponentDelegate()...インターフェイスを実装する匿名タイプを宣言します。

于 2010-02-02T19:33:33.620 に答える
0

リフレクションを使用したソリューションの例、渡されたメソッドはパブリックである必要があります

import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;

public class Program {
    int i;

    public static void main(String[] args) {
        Program   obj = new Program();    //some object

        try {
            Method method = obj.getClass().getMethod("target");
            repeatMethod( 5, obj, method );
        } 
        catch ( NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            System.out.println( e ); 
        }
    }

    static void repeatMethod (int times, Object object, Method method)
        throws IllegalAccessException, InvocationTargetException {

        for (int i=0; i<times; i++)
            method.invoke(object);
    }
    public void target() {                 //public is necessary
        System.out.println("target(): "+ ++i);
    }
}
于 2019-09-22T20:53:04.207 に答える