Java에서의 콜백 함수
Java 메서드에서 콜백 함수를 전달하는 방법이 있나요?
제가 흉내내려고 하는 동작은 입니다.함수에 전달되는 넷 위임입니다.
다른 오브젝트를 만들자고 제안하는 사람들을 본 적이 있지만, 그것은 과잉인 것 같습니다만, 때때로 과잉 살상이 유일한 방법이라는 것을 알고 있습니다.
같은 것을 말하는 경우.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 이후 lamda 및 메서드 참조가 있습니다.
를 들어,하는 인터페이스 「」가 한 경우는, 「」를 참조해 주세요.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
:
@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"
또한 예외도 설정할 수 있습니다.
@FunctionalInterface
interface FallibleFunction<In, Out, Ex extends Exception> {
Out get(In input) throws Ex;
}
public <Ex extends IOException> String yo(FallibleFunction<Integer, String, Ex> f) throws Ex {
return f.get(42);
}
Runnable을 사용하면 간단하게 할 수 있습니다.
private void runCallback(Runnable callback)
{
// Run callback
callback.run();
}
사용방법:
runCallback(new Runnable()
{
@Override
public void run()
{
// Running callback
}
});
하지만 내가 찾던 방법 중 가장 선호하는 방법이 있다는 걸 알 수 있어.기본적으로는 이 답변에서 도출된 것이지만, 저는 좀 더 중복되고 효율적으로 조작해야 했습니다.내가 생각해낸 걸 찾는 모든 사람들이
요점:
먼저 인터페이스를 그렇게 단순하게 만듭니다.
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
에 콜백의 로 이 합니다.이 함수에 콜백인터페이스를 파라미터로 추가합니다.
내 요점이 명확하길 바라며 즐기세요;)
사소한 트집:
나는 사람들이 다른 물체를 만들자고 제안해 왔지만 그것은 과잉인 것 같다.
콜백 전달에는 거의 모든 OO 언어로 별도의 오브젝트를 생성하는 것이 포함되므로 오버킬이라고 보기 어렵습니다.즉, Java에서는 별도의 클래스를 만들어야 합니다.이 클래스는 명시적으로 퍼스트 클래스 함수나 닫힘이 있는 언어보다 상세하고 리소스 집약적입니다.그러나 익명 클래스는 최소한 장황함을 줄이고 인라인에서 사용할 수 있습니다.
이것은 람다를 사용하는 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);
}
}
}
메서드는 Java에서 아직 퍼스트 클래스 개체가 아니므로 함수 포인터를 콜백으로 전달할 수 없습니다.대신 필요한 메서드를 포함하는 오브젝트(통상은 인터페이스를 실장)를 생성하여 전달합니다.
Java에서의 폐쇄에 대한 제안(당신이 원하는 동작을 제공함)이 이루어졌지만, 다가오는 Java 7 릴리즈에는 포함되지 않을 것입니다.
자바에서 이런 기능이 필요할 때 주로 옵저버 패턴을 사용합니다.추가 객체를 의미하지만, 저는 이것이 깔끔한 방법이라고 생각합니다.또한 코드 판독에 도움이 되는 널리 알려진 패턴이라고 생각합니다.
폐쇄가 람다지 라이브러리에서 어떻게 구현되었는지 확인합니다.실제로는 C#의 위임자와 매우 유사한 동작을 합니다.
http://code.google.com/p/lambdaj/wiki/Closures
, 할 수요.Callback
Delegate
★★★★
콜백자바
public interface Callback {
void onItemSelected(int position);
}
Pager Activity.java
public class PagerActivity implements Callback {
CustomPagerAdapter mPagerAdapter;
public PagerActivity() {
mPagerAdapter = new CustomPagerAdapter(this);
}
@Override
public void onItemSelected(int position) {
// Do something
System.out.println("Item " + postion + " selected")
}
}
CustomPagerAdapter.java
public class CustomPagerAdapter {
private static final int DEFAULT_POSITION = 1;
public CustomPagerAdapter(Callback callback) {
callback.onItemSelected(DEFAULT_POSITION);
}
}
java.lang.reflect를 사용하여 '콜백'을 구현하려고 했습니다.다음은 예를 제시하겠습니다.
package StackOverflowQ443708_JavaCallBackTest;
import java.lang.reflect.*;
import java.util.concurrent.*;
class MyTimer
{
ExecutorService EXE =
//Executors.newCachedThreadPool ();
Executors.newSingleThreadExecutor ();
public static void PrintLine ()
{
System.out.println ("--------------------------------------------------------------------------------");
}
public void SetTimer (final int timeout, final Object obj, final String methodName, final Object... args)
{
SetTimer (timeout, obj, false, methodName, args);
}
public void SetTimer (final int timeout, final Object obj, final boolean isStatic, final String methodName, final Object... args)
{
Class<?>[] argTypes = null;
if (args != null)
{
argTypes = new Class<?> [args.length];
for (int i=0; i<args.length; i++)
{
argTypes[i] = args[i].getClass ();
}
}
SetTimer (timeout, obj, isStatic, methodName, argTypes, args);
}
public void SetTimer (final int timeout, final Object obj, final String methodName, final Class<?>[] argTypes, final Object... args)
{
SetTimer (timeout, obj, false, methodName, argTypes, args);
}
public void SetTimer (final int timeout, final Object obj, final boolean isStatic, final String methodName, final Class<?>[] argTypes, final Object... args)
{
EXE.execute (
new Runnable()
{
public void run ()
{
Class<?> c;
Method method;
try
{
if (isStatic) c = (Class<?>)obj;
else c = obj.getClass ();
System.out.println ("Wait for " + timeout + " seconds to invoke " + c.getSimpleName () + "::[" + methodName + "]");
TimeUnit.SECONDS.sleep (timeout);
System.out.println ();
System.out.println ("invoking " + c.getSimpleName () + "::[" + methodName + "]...");
PrintLine ();
method = c.getDeclaredMethod (methodName, argTypes);
method.invoke (obj, args);
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
PrintLine ();
}
}
}
);
}
public void ShutdownTimer ()
{
EXE.shutdown ();
}
}
public class CallBackTest
{
public void onUserTimeout ()
{
System.out.println ("onUserTimeout");
}
public void onTestEnd ()
{
System.out.println ("onTestEnd");
}
public void NullParameterTest (String sParam, int iParam)
{
System.out.println ("NullParameterTest: String parameter=" + sParam + ", int parameter=" + iParam);
}
public static void main (String[] args)
{
CallBackTest test = new CallBackTest ();
MyTimer timer = new MyTimer ();
timer.SetTimer ((int)(Math.random ()*10), test, "onUserTimeout");
timer.SetTimer ((int)(Math.random ()*10), test, "onTestEnd");
timer.SetTimer ((int)(Math.random ()*10), test, "A-Method-Which-Is-Not-Exists"); // java.lang.NoSuchMethodException
timer.SetTimer ((int)(Math.random ()*10), System.out, "println", "this is an argument of System.out.println() which is called by timer");
timer.SetTimer ((int)(Math.random ()*10), System.class, true, "currentTimeMillis");
timer.SetTimer ((int)(Math.random ()*10), System.class, true, "currentTimeMillis", "Should-Not-Pass-Arguments"); // java.lang.NoSuchMethodException
timer.SetTimer ((int)(Math.random ()*10), String.class, true, "format", "%d %X", 100, 200); // java.lang.NoSuchMethodException
timer.SetTimer ((int)(Math.random ()*10), String.class, true, "format", "%d %X", new Object[]{100, 200});
timer.SetTimer ((int)(Math.random ()*10), test, "NullParameterTest", new Class<?>[]{String.class, int.class}, null, 888);
timer.ShutdownTimer ();
}
}
저는 최근에 다음과 같은 일을 시작했습니다.
public class Main {
@FunctionalInterface
public interface NotDotNetDelegate {
int doSomething(int a, int b);
}
public static void main(String[] args) {
// in java 8 (lambdas):
System.out.println(functionThatTakesDelegate((a, b) -> {return a*b;} , 10, 20));
}
public static int functionThatTakesDelegate(NotDotNetDelegate del, int a, int b) {
// ...
return del.doSomething(a, b);
}
}
좀낡낡 했지지 ...... 도......피터 윌킨슨, int/integer.는 '○○'입니다..getClass()
★★★★★★★★★★★★★★★★의 경우parameters[i]
예를 들어 다음과 같이 반환됩니다.java.lang.Integer
, 이 은 잘못 될 수 있습니다.getMethod(methodName,parameters[])
(웃음)
나는 그것을 Daniel Spiewak의 제안과 결합했다(이에 대한 답변). 성공으로 가는 단계에는 캐치핑이 포함되어 있다.NoSuchMethodException
->getMethods()
> > > > > > > > > > > > > > > > > > > > > >method.getName()
다음으로 파라미터 목록을 명시적으로 루프하여 Daniels 솔루션을 적용합니다.이러한 유형의 식별과 시그니처가 일치합니다.
Java 8에서는 이 작업은 비교적 간단합니다.멀티패키지 시나리오에서 콜백을 사용하고 싶다면 다음과 같은 작업을 수행할 수 있습니다.
public void methodA (int n, IntConsumer consumer) {
// create a thread
Thread t = new Thread(() -> {
// some time consuming operation
int result = IntStream.range(0, n).sum();
// after the result is ready do something with it.
consumer.accept(result);
});
t.start();
}
이 방법을 사용하려면 다음 작업을 수행합니다.
methodA(1000000, System.out::println);
public class HelloWorldAnonymousClasses {
//this is an interface with only one method
interface HelloWorld {
public void printSomething(String something);
}
//this is a simple function called from main()
public void sayHello() {
//this is an object with interface reference followed by the definition of the interface itself
new HelloWorld() {
public void printSomething(String something) {
System.out.println("Hello " + something);
}
}.printSomething("Abhi");
//imagine this as an object which is calling the function'printSomething()"
}
public static void main(String... args) {
HelloWorldAnonymousClasses myApp =
new HelloWorldAnonymousClasses();
myApp.sayHello();
}
}
//Output is "Hello Abhi"
기본적으로 인터페이스의 오브젝트를 만드는 경우 인터페이스는 오브젝트를 가질 수 없기 때문에 불가능합니다.
옵션은 일부 클래스에서 인터페이스를 구현한 후 해당 클래스의 개체를 사용하여 해당 함수를 호출하는 것입니다.하지만 이 접근법은 정말 장황하다.
또는 새로운 HelloWorld()를 기입하고(*이것은 클래스가 아닌 인터페이스입니다), 그 후에 인터페이스 메서드 자체의 디피네이션(*이 디피네이션은 실제로는 어나니머스 클래스입니다.그런 다음 메서드 자체를 호출할 수 있는 개체 참조를 가져옵니다.
인터페이스를 만들고 콜백클래스에서 같은 인터페이스 속성을 만듭니다.
interface dataFetchDelegate {
void didFetchdata(String data);
}
//callback class
public class BackendManager{
public dataFetchDelegate Delegate;
public void getData() {
//Do something, Http calls/ Any other work
Delegate.didFetchdata("this is callbackdata");
}
}
여기서 콜백하는 클래스에서 위의 Created Interface를 구현합니다.또한 호출할 클래스의 "this" 객체/참조도 전달합니다.
public class Main implements dataFetchDelegate
{
public static void main( String[] args )
{
new Main().getDatafromBackend();
}
public void getDatafromBackend() {
BackendManager inc = new BackendManager();
//Pass this object as reference.in this Scenario this is Main Object
inc.Delegate = this;
//make call
inc.getData();
}
//This method is called after task/Code Completion
public void didFetchdata(String callbackData) {
// TODO Auto-generated method stub
System.out.println(callbackData);
}
}
가장 간단하고 쉬운 방법은 재사용 가능한 모델을 만들고 트리거하는 것입니다.https://onecompiler.com/java/3wejrcby2?fbclid=IwAR0dHbGDChRUJoCZ3CIDW-JQu7Dz3iYGNGYjxYVCPCWfEqQDogFGTwuOuO8
언급URL : https://stackoverflow.com/questions/443708/callback-functions-in-java
'itsource' 카테고리의 다른 글
Rubaxa-Sortable이 'Element'에서 'matches'를 실행하지 못했습니다. '>*'는 올바른 선택기가 아닙니다. (0) | 2022.08.14 |
---|---|
Junit 테스트에서 기본 Spring-Boot application.properties 설정을 덮어씁니다. (0) | 2022.08.14 |
정적 컨텍스트에서 리소스 컨텐츠를 가져오려면 어떻게 해야 합니까? (0) | 2022.08.14 |
Vue.js: 조건부 클래스 스타일 바인딩 (0) | 2022.08.14 |
Vue.js에서 optgroup select 라벨을 설정하는 방법 (0) | 2022.08.14 |