[java] Java의 콜백 함수

Java 메소드에서 콜백 함수를 전달하는 방법이 있습니까?

내가 모방하려는 행동은 .Net Delegate가 함수에 전달되는 것입니다.

사람들이 별도의 객체를 만들 것을 제안하는 것을 보았지만 과잉으로 보이지만 때로는 과잉이 유일한 방법이라는 것을 알고 있습니다.



답변

.NET 익명 대리자와 같은 것을 의미한다면 Java의 익명 클래스도 사용할 수 있다고 생각합니다.

public class Main {

    public interface Visitor{
        int doJob(int a, int b);
    }


    public static void main(String[] args) {
        Visitor adder = new Visitor(){
            public int doJob(int a, int b) {
                return a + b;
            }
        };

        Visitor multiplier = new Visitor(){
            public int doJob(int a, int b) {
                return a*b;
            }
        };

        System.out.println(adder.doJob(10, 20));
        System.out.println(multiplier.doJob(10, 20));

    }
}


답변

Java 8부터 람다 및 메소드 참조가 있습니다.

예를 들어 다음 A -> B과 같은 기능 인터페이스를 원할 경우

import java.util.function.Function;

public MyClass {
    public static String applyFunction(String name, Function<String,String> function){
        return function.apply(name);
    }
}

그럼 그렇게 불러

MyClass.applyFunction("42", str -> "the answer is: " + str);
// returns "the answer is: 42"

또한 클래스 메소드를 전달할 수 있습니다. 당신이 가지고 있다고 :

@Value // lombok
public class PrefixAppender {
    private String prefix;

    public String addPrefix(String suffix){
        return prefix +":"+suffix;
    }
}

그럼 당신은 할 수 있습니다 :

PrefixAppender prefixAppender= new PrefixAppender("prefix");
MyClass.applyFunction("some text", prefixAppender::addPrefix);
// returns "prefix:some text"

참고 :

여기서는 기능 인터페이스 Function<A,B>를 사용했지만 패키지에는 다른 인터페이스 가 많이 있습니다 java.util.function. 가장 주목할만한 것은

  • Supplier: void -> A
  • Consumer: A -> void
  • BiConsumer: (A,B) -> void
  • Function: A -> B
  • BiFunction: (A,B) -> C

입 / 출력 유형 중 일부를 전문으로하는 다른 많은 것. 그런 다음 필요한 기능을 제공하지 않으면 다음과 같이 자체 기능 인터페이스를 만들 수 있습니다.

@FunctionalInterface
interface Function3<In1, In2, In3, Out> { // (In1,In2,In3) -> Out
    public Out apply(In1 in1, In2 in2, In3 in3);
}

사용 예 :

String computeAnswer(Function3<String, Integer, Integer, String> f){
    return f.apply("6x9=", 6, 9);
}

computeAnswer((question, a, b) -> question + "42");
// "6*9=42"


답변

간단히하기 위해 Runnable을 사용할 수 있습니다 .

private void runCallback(Runnable callback)
{
    // Run callback
    callback.run();
}

용법:

runCallback(new Runnable()
{
    @Override
    public void run()
    {
        // Running callback
    }
});


답변

조금 따끔 따끔 :

사람들이 별도의 객체를 만들 것을 제안하는 것처럼 보였지만 과잉으로 보입니다.

콜백을 전달하는 것은 거의 모든 OO 언어로 별도의 객체를 생성하는 것을 포함하므로 과잉으로 간주 될 수 없습니다. 아마도 자바에서 별도의 클래스를 만들어야한다는 것입니다.이 클래스는 명시 적 일류 함수 또는 클로저가있는 언어보다 더 장황하고 자원 집약적입니다. 그러나 익명 클래스는 최소한 세부 정보를 줄이고 인라인으로 사용할 수 있습니다.


답변

그러나 나는 그것이 기본적으로 이러한 답변에서 파생 무슨 내가 찾던 ..이었다 가장 선호하는 방법이 볼 수 있지만 나는 그것을 더 이상 중복 효율적으로 조작했다 … 그리고 난 모든 사람들이 내가 가지고 올 것을 찾고 생각

요점 ::

먼저 간단한 인터페이스 만듭니다.

public interface myCallback {
    void onSuccess();
    void onError(String err);
}

결과를 처리하려고 할 때 마다이 콜백을 실행하십시오. 비동기 호출 후 더 가능성이 높으며 이러한 재사용에 의존하는 일부 항목을 실행하고 싶습니다.

// import the Interface class here

public class App {

    public static void main(String[] args) {
        // call your method
        doSomething("list your Params", new myCallback(){
            @Override
            public void onSuccess() {
                // no errors
                System.out.println("Done");
            }

            @Override
            public void onError(String err) {
                // error happen
                System.out.println(err);
            }
        });
    }

    private void doSomething(String param, // some params..
                             myCallback callback) {
        // now call onSuccess whenever you want if results are ready
        if(results_success)
            callback.onSuccess();
        else
            callback.onError(someError);
    }

}

doSomething 콜백을 추가하여 결과가 왔을 때 알리고 콜백 인터페이스를이 메소드에 매개 변수로 추가하는 데 시간이 걸리는 함수입니다.

내 요점이 분명하길 바랍니다.)


답변

람다가있는 Java 8에서는 매우 쉽습니다.

public interface Callback {
    void callback();
}

public class Main {
    public static void main(String[] args) {
        methodThatExpectsACallback(() -> System.out.println("I am the callback."));
    }
    private static void methodThatExpectsACallback(Callback callback){
        System.out.println("I am the method.");
        callback.callback();
    }
}


답변

리플렉션 라이브러리를 사용하여 구현하는 아이디어가 흥미 롭다는 것을 알았고 꽤 잘 작동한다고 생각했습니다. 유일한 단점은 유효한 매개 변수를 전달하고 있는지 컴파일 시간 검사를 잃는 것입니다.

public class CallBack {
    private String methodName;
    private Object scope;

    public CallBack(Object scope, String methodName) {
        this.methodName = methodName;
        this.scope = scope;
    }

    public Object invoke(Object... parameters) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        Method method = scope.getClass().getMethod(methodName, getParameterClasses(parameters));
        return method.invoke(scope, parameters);
    }

    private Class[] getParameterClasses(Object... parameters) {
        Class[] classes = new Class[parameters.length];
        for (int i=0; i < classes.length; i++) {
            classes[i] = parameters[i].getClass();
        }
        return classes;
    }
}

당신은 이것을 이렇게 사용합니다

public class CallBackTest {
    @Test
    public void testCallBack() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        TestClass testClass = new TestClass();
        CallBack callBack = new CallBack(testClass, "hello");
        callBack.invoke();
        callBack.invoke("Fred");
    }

    public class TestClass {
        public void hello() {
            System.out.println("Hello World");
        }

        public void hello(String name) {
            System.out.println("Hello " + name);
        }
    }
}