Java - asynchronous methods with return value

2019-08-29 09:02发布

I have a question about asynchronous method calls in java, especially about the response value of the async method.

The situation is the following:

The async method I want to call is..

public void getSpeed(IResponseListener listener) {
....
}

The interface of the listener is...

interface IResponseListener {
    public void response(ResponseEvent event);
}

This method is called when the async method has a response value

My problem now is that the class ResponseEvent has an attribute response that can be of any type (boolean,float,String...)and in the implementation of the interface IResponseListener I have to cast the value...

IResponseListener listener = new IResponseListener {

    public void response(ResponseEvent event) {
        float f = (float)event.response;
    }
}

Is this a good solution to handle this? I think the bad thing is that the response listener HAS to know the type of the response! Is there a better solution to handle asynchronous calls that want to give a response even if the response can be of any type?

4条回答
不美不萌又怎样
2楼-- · 2019-08-29 09:26

I don't know whether this is correct, but if you are going to handle the return value differently, why not overload the response method with different type of objects that you would expect. Just a suggestion..

interface InterfaceName{
    void response(float responseVal);
    void response(boolean responseVal);
    ...
}
查看更多
甜甜的少女心
3楼-- · 2019-08-29 09:28

Use Java generics:

interface IResponseListener<T> {
    public void response(T response);
}

Then, in an anonymous class:

IResponseListener listener = new IResponseListener<Float> {

    public void response(Float response) {
        float f = response;
    }
}
查看更多
时光不老,我们不散
4楼-- · 2019-08-29 09:35

I would have done as @nico_ekito says...Or use your existing solution. It is a problem that you don't know the result type.

Anyway, you could do some adjustments and let the ResponseEvent class do the casting for you.

ResponseListener.java

interface IResponseListener {
    void response(ResponseEvent event);
}

ResponseEvent.java

public class ResponseEvent {

   private Object response;

   @SuppressWarnings("unchecked")
   public <T> T getResponse() {
       return (T)response;
   }

   public <T> void setResponse(T response) {
       this.response = response;
   }
}

Usage:

IResponseListener listener = new IResponseListener() {
    public void response(ResponseEvent event) {
        float f = event.getResponse();
    } 
};

Please note that you will get a ClassCastException if your type is something other than what you expect it to be.

查看更多
戒情不戒烟
5楼-- · 2019-08-29 09:37

I think a lot of these answers are starting to look like this->

public interface Function<Args, Value>
{
  public Value call(Args args);
}

Your return type doesn't matter--if it can return multiple types, then the "multiple types" are a type...might I suggest a type of JSON considering what you're looking at?

The reality is you can't expect your handler to know the type in advance so you need to specify that. Whether this is with the return type or the class is up to you.

I could easily see doing a class hierarchy:

public class ResponseString implements Function<Args, String>; 
public class ResponseNumber implements Function<Args, Number>;
...
public class ResponseType implements Function<Args, Type>;

or simply creating a type that has all the information you need. The long and short is that the method can DEFINE what it expects for the types and you have the ability to extend them. Keep in mind that response could also be a Function which could be executed. There's nothing wrong with knowing what to DO with something and not knowing what it is ->

Example->

//Admittedly I'd probably have a "Procedure or VoidFunction interface as well".
public yourMethod(Function<String args, Function<String,?> handler)
{
  String hello = "hello";
  Function<String,?> function = handler.call(hello);
  function.call(hello); 
} 

I hope this helps. Sometimes there's no reason to go this far, and sometimes there is. You don't know the type--it seems like maybe you're hoping someone else will provide it and this can do that for you while remaining strict.

EDIT: the example of have for this in one framework is:

  Applcation.openDialog(Dialog dialog, Callable<Boolean> onClose);

This returns true of the dialog cleans up and closes and false if not. I don't really care what happens here, I do care that it tells me yes, close it, or no don't.

查看更多
登录 后发表回答