ฟังก์ชั่นการโทรกลับใน Java


177

มีวิธีการส่งผ่านฟังก์ชั่นโทรกลับในวิธีการจาวาหรือไม่?

พฤติกรรมที่ฉันพยายามเลียนแบบคือ. Net Delegate ที่ถูกส่งผ่านไปยังฟังก์ชัน

ฉันเคยเห็นผู้คนแนะนำให้สร้างวัตถุแยกต่างหาก แต่ดูเหมือนว่ามีราคาเกินจริง แต่ฉันรู้ว่าบางครั้งการเติมเต็มเป็นวิธีเดียวที่จะทำสิ่งต่าง ๆ


51
มัน overkill เพราะ Java นั้นใช้งานไม่ได้ (ซึ่งควรจะเป็น pun ... )
Keith Pinson

อีกตัวอย่างของ java 8: stackoverflow.com/questions/14319787/ …
Vadzim

คำตอบ:


155

ถ้าคุณหมายถึงบางอย่างเช่น. ผู้แทนที่ไม่ระบุชื่อ. NET ฉันคิดว่า Java class ไม่ระบุชื่อสามารถใช้ได้เช่นกัน

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));

    }
}

3
นี่เป็นวิธีมาตรฐานตั้งแต่จาวา 1.0
ชาร์ลีมาร์ติน

1
ฉันเคยได้รับสิ่งนี้มันเป็น verbose มากกว่าสิ่งที่ฉันต้องการ แต่มันก็ใช้งานได้ดี
Omar Kooheji

23
@ Omar เห็นด้วย ฉันกลับมาที่ Java หลังจากใช้ C # มานานและคิดถึงลูกแกะ / ผู้ได้รับมอบหมาย มาที่ Java!
Drew Noakes

4
@DrewNoakes ข่าวดีก็คือJava 8มี lambdas (ส่วนใหญ่) ...
ลูคัส

2
เนื่องจากคุณได้กำหนดอินเทอร์เฟซผู้เข้าชมด้วยวิธีการเดียวคุณสามารถส่งลูกแกะที่ตรงกับมันแทนได้
Joey Baruch

43

ตั้งแต่ 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"

1
สำหรับ CallBacks จะเป็นการดีกว่าที่จะเขียนอินเตอร์เฟสการทำงานของคุณเองเนื่องจากการโทรกลับแต่ละประเภทมักจะมีหลายไวยากรณ์
Sri Harsha Chilakapati

ฉันไม่แน่ใจที่จะเข้าใจ หากหนึ่งในชั้นเรียนjava.util.functionเป็นสิ่งที่คุณกำลังมองหาแล้วคุณจะไปดี จากนั้นคุณสามารถเล่นกับ generics สำหรับ I / O (?)
Juh_

คุณไม่เข้าใจฉันสิ่งที่ฉันพูดเกี่ยวกับการแปลรหัส C ++ ซึ่งใช้ฟังก์ชั่นการโทรกลับไปยัง Java 8 ที่นั่นสำหรับตัวชี้ฟังก์ชั่นเฉพาะแต่ละตัวคุณต้องสร้างส่วนต่อประสานการทำงานใน Java เนื่องจากจะมีพารามิเตอร์มากขึ้น รหัสการผลิต
Sri Harsha Chilakapati

2
ข้อสรุปของฉันคือส่วนใหญ่คุณจะต้องเขียนอินเทอร์เฟซการทำงานของคุณเองตั้งแต่ค่าเริ่มต้นที่ให้ไว้java.util.functionไม่เพียงพอ
Sri Harsha Chilakapati

1
ฉันได้เพิ่มบันทึกย่อเกี่ยวกับส่วนต่อประสานการทำงานที่มีอยู่และวิธีการสร้างรายการใหม่
Juh_

28

เพื่อความง่ายคุณสามารถใช้Runnable :

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

การใช้งาน:

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

2
ฉันชอบสิ่งนี้เพราะฉันไม่จำเป็นต้องสร้างอินเทอร์เฟซใหม่หรือคลาสเพียงเพื่อโทรกลับอย่างง่าย ขอบคุณสำหรับทิป!
บรูซ

1
public interface SimpleCallback { void callback(Object... objects); }มันค่อนข้างตรงไปตรงมาและอาจมีประโยชน์คุณต้องผ่าน params บ้างเช่นกัน
มาร์โกซี

@cprcrack ไม่มีวิธีส่งค่าในฟังก์ชั่น run () หรือไม่?
Chris Chevalier

16

nitpicking เล็กน้อย:

ฉันดูเหมือนคนที่แนะนำให้สร้างวัตถุแยกต่างหาก แต่ดูเหมือนว่าเกินความเป็นจริง

การส่งผ่านการเรียกกลับรวมถึงการสร้างวัตถุแยกต่างหากในภาษา OO เกือบทั้งหมดดังนั้นมันจึงแทบไม่ได้รับการพิจารณามากเกินไป สิ่งที่คุณอาจหมายถึงคือใน Java คุณต้องสร้างคลาสแยกต่างหากซึ่งเป็น verbose (และใช้ทรัพยากรมาก) มากกว่าในภาษาที่มีฟังก์ชั่นหรือการปิดชั้นหนึ่งอย่างชัดเจน อย่างไรก็ตามคลาสที่ไม่ระบุชื่ออย่างน้อยก็ลดความฟุ่มเฟื่อยและสามารถใช้แบบอินไลน์


12
ใช่นั่นคือสิ่งที่ฉันหมายถึง ด้วยเหตุการณ์ 30 เหตุการณ์หรือมากกว่านั้นคุณจะจบด้วย 30 คลาส
Omar Kooheji

16

แต่ฉันเห็นว่ามีวิธีที่ต้องการมากที่สุดซึ่งเป็นสิ่งที่ฉันกำลังมองหา .. มันมาจากคำตอบเหล่านี้โดยทั่วไป แต่ฉันต้องจัดการกับมันซ้ำซ้อนและมีประสิทธิภาพมากขึ้น .. และฉันคิดว่าทุกคนกำลังมองหาสิ่งที่ฉันมาด้วย

ถึงจุด ::

ก่อนอื่นให้สร้างส่วนต่อประสานที่เรียบง่าย

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

ตอนนี้เพื่อให้การเรียกกลับนี้ทำงานเมื่อคุณต้องการจัดการผลลัพธ์ - มีแนวโน้มมากขึ้นหลังจากการโทรแบบ async และคุณต้องการเรียกใช้บางสิ่งซึ่งขึ้นอยู่กับ reuslts เหล่านี้

// 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 เป็นฟังก์ชั่นที่ใช้เวลาพอสมควรที่คุณต้องการเพิ่มการติดต่อกลับเพื่อแจ้งให้คุณทราบเมื่อผลลัพธ์มาเพิ่มอินเทอร์เฟซการโทรกลับเป็นพารามิเตอร์ในวิธีการนี้

หวังว่าจุดของฉันชัดเจนเพลิดเพลิน;)


11

นี่เป็นเรื่องง่ายมากใน Java 8 ที่มี lambdas

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();
    }
}

มันจะเป็นแบบนี้ในกรณีที่มีข้อโต้แย้ง? pastebin.com/KFFtXPNA
Nashev

1
อ๋อ จำนวนข้อโต้แย้งใด ๆ (หรือไม่มี) จะทำงานตราบเท่าที่ไวยากรณ์แลมบ์ดาเหมาะสม
gk bwg rhb mbreafteahbtehnb

7

ฉันพบความคิดในการใช้งานรีเฟลคชันไลบรารี่ที่น่าสนใจและคิดว่าสิ่งนี้ใช้ได้ดี ข้อเสียเพียงอย่างเดียวคือการสูญเสียเวลาในการตรวจสอบการรวบรวมว่าคุณผ่านพารามิเตอร์ที่ถูกต้อง

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);
        }
    }
}

ดูเหมือนเล็กน้อย (/ เป็ดฉัน)
Diederik

ขึ้นอยู่กับจำนวนการใช้งานและขนาดของโครงการ: overkill สำหรับโครงการขนาดเล็กใช้งานได้จริงในขนาดใหญ่
Juh_

ลองดูคำตอบของ @monnoo
Juh_

5

วิธีการยังไม่ได้เป็นวัตถุชั้นหนึ่งใน Java; คุณไม่สามารถส่งผ่านตัวชี้ฟังก์ชันเป็นการโทรกลับ สร้างวัตถุ (ซึ่งมักจะใช้อินเทอร์เฟซ) แทนซึ่งประกอบด้วยวิธีที่คุณต้องการและส่งผ่านนั้น

ข้อเสนอสำหรับการปิดใน Java ซึ่งจะให้พฤติกรรมที่คุณกำลังมองหาได้รับการทำ แต่จะไม่มีการรวมอยู่ในการเปิดตัว Java 7 ที่จะมาถึง


1
"วิธีการยังไม่ได้เป็นวัตถุชั้นหนึ่งใน Java" - ดีมีวิธีการระดับ [1] ซึ่งคุณสามารถส่งผ่านอินสแตนซ์ มันไม่ใช่รหัส OO ที่สะอาด, เป็นไปได้, ที่คุณคาดหวังจากจาวา แต่อาจจะสะดวกกว่า สิ่งที่ต้องพิจารณาแน่นอน [1] java.sun.com/j2se/1.4.2/docs/api/java/lang/reflect/Method.html
Jonas Kölker

4

เมื่อฉันต้องชนิดของการทำงานในชวานี้ผมมักจะใช้รูปแบบการสังเกตการณ์ มันแสดงถึงวัตถุพิเศษ แต่ฉันคิดว่ามันเป็นวิธีที่สะอาดตาและเป็นรูปแบบที่เข้าใจกันอย่างกว้างขวางซึ่งช่วยในการอ่านโค้ดได้



3

ฉันพยายามใช้ java.lang.reflect เพื่อใช้ 'callback' ต่อไปนี้เป็นตัวอย่าง:

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 ();
    }
}

คุณจะผ่านเป็นโมฆะเป็น arg ได้อย่างไร
TWiStErRob

@TWiStErRob ในตัวอย่างนี้จะเป็นเช่นtimer.SetTimer ((int)(Math.random ()*10), System.out, "printf", "%s: [%s]", new Object[]{"null test", null});นั้น ผลผลิตจะเป็นnull test: [null]
LiuYan 刘研

จะไม่เปิด NPE args[i].getClass()หรือ ประเด็นของฉันคือมันไม่ทำงานถ้าคุณเลือกวิธีการตามประเภทของอาร์กิวเมนต์ ใช้งานได้String.formatแต่ไม่สามารถทำงานกับสิ่งอื่นที่ยอมรับnullได้
TWiStErRob

@TWiStErRob จุดดี! ฉันได้เพิ่มฟังก์ชั่นที่สามารถส่งผ่านargTypesอาร์เรย์ด้วยตนเองดังนั้นตอนนี้เราสามารถผ่านnullอาร์กิวเมนต์ / พารามิเตอร์โดยไม่ต้อง NullPointerException เกิดขึ้น เอาต์พุตตัวอย่าง:NullParameterTest: String parameter=null, int parameter=888
LiuYan 刘研

3

คุณยังสามารถทำได้Callbackโดยใช้Delegateรูปแบบ:

Callback.java

public interface Callback {
    void onItemSelected(int position);
}

PagerActivity.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);
    }
}

1

ฉันเพิ่งเริ่มทำสิ่งนี้:

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);
    }
}

1

มันค่อนข้างเก่า แต่กระนั้น ... ฉันพบคำตอบของ Peter Wilkinson เป็นคนดียกเว้นความจริงที่ว่ามันใช้งานไม่ได้กับประเภทดั้งเดิมเช่น int / Integer ปัญหาคือ.getClass()สำหรับparameters[i], ซึ่งส่งคืนอินสแตนซ์java.lang.Integer, ซึ่งในทางกลับกันจะไม่ถูกตีความอย่างถูกต้องโดยgetMethod(methodName,parameters[])(ความผิดของ Java) ...

ฉันรวมกับข้อเสนอแนะของ Daniel Spiewak ( ในคำตอบของเขากับเรื่องนี้ ); ขั้นตอนสู่ความสำเร็จรวมถึง: การจับNoSuchMethodException-> getMethods()-> มองหาการจับคู่ทีละตัวmethod.getName()-> จากนั้นวนลูปอย่างชัดเจนผ่านรายการพารามิเตอร์และใช้โซลูชันแดเนียลส์เช่นการระบุประเภทการจับคู่และการจับคู่ลายเซ็น


0

ฉันคิดว่าการใช้คลาสนามธรรมนั้นสง่างามกว่านี้:

// Something.java

public abstract class Something {   
    public abstract void test();        
    public void usingCallback() {
        System.out.println("This is before callback method");
        test();
        System.out.println("This is after callback method");
    }
}

// CallbackTest.java

public class CallbackTest extends Something {
    @Override
    public void test() {
        System.out.println("This is inside CallbackTest!");
    }

    public static void main(String[] args) {
        CallbackTest myTest = new CallbackTest();
        myTest.usingCallback();
    }    
}

/*
Output:
This is before callback method
This is inside CallbackTest!
This is after callback method
*/

นี่คือความหลากหลายไม่ใช่การติดต่อกลับ คุณต้องตรวจสอบรูปแบบการโทรกลับ
simo.3792

ใช่ฉันกำลังใช้ความหลากหลายในการโทรกลับจากชั้นยอด คุณไม่ได้รับฟังก์ชั่นนี้ง่ายๆโดย polymorphism ฉันกำลังเรียกใช้ usingCallback () ซึ่งอยู่ใน Class Something จากนั้นจะโทรกลับไปที่คลาสย่อยที่ผู้ใช้เขียนการทดสอบการทำงาน ()
avatar1337

2
การโทรกลับได้รับการออกแบบมาเพื่อobjectให้ "แจ้งเตือน" อีกครั้งobjectเมื่อเกิดเหตุการณ์ที่มีนัยสำคัญดังนั้นเหตุการณ์ที่สองobjectจึงสามารถจัดการเหตุการณ์ได้ คุณabstract classไม่เคยแยกจากกันobjectแต่แยกจากกันclassเท่านั้น คุณใช้เพียงอย่างเดียวobjectและแตกต่างกันclassesในการทำหน้าที่ต่าง ๆ ซึ่งเป็นสาระสำคัญของความหลากหลายไม่ใช่รูปแบบการโทรกลับ
simo.3792

0
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 () (* oberserve นี่เป็นอินเทอร์เฟซที่ไม่ใช่คลาส) แล้วตามด้วยการกำหนดวิธีการอินเทอร์เฟซเอง (* การกำหนดนี้เป็นจริงในระดับที่ไม่ระบุชื่อ) จากนั้นคุณจะได้รับการอ้างอิงวัตถุซึ่งคุณสามารถเรียกใช้เมธอดเองได้


0

สร้างอินเทอร์เฟซและสร้างคุณสมบัติอินเทอร์เฟซเดียวกันในคลาสการเรียกกลับ

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");
   }

}

ขณะนี้อยู่ในคลาสที่คุณต้องการเรียกกลับให้ใช้อินเตอร์เฟสที่สร้างขึ้นด้านบน และยังผ่านวัตถุนี้ / อ้างอิงของชั้นเรียนของคุณที่จะถูกเรียกกลับ

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);
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.