如何从单个方法返回不同的数据类型?

时间:2017-04-28 13:40:05

标签: java java-8

我的代码如下。

我希望根据状态代码获取不同的错误消息,如果成功则应该返回对象.. 如何从一种方法返回这种不同的数据类型?

public EstimateTimeResult getEstimateTime(@RequestBody EstimateTimeCall estimateTimeCall,@PathVariable("empid") Long empid) throws IOException{
        String URL=baseApi+"/estimates/time";
        if(estimateTimeCall.getProduct_id().isEmpty() || estimateTimeCall.getProduct_id()==null || estimateTimeCall.getProduct_id()==""){
            URL+="?start_latitude="+estimateTimeCall.getStart_latitude().toString()+"&start_longitude="+estimateTimeCall.getStart_longitude().toString();
        }else{
            URL+="?start_latitude="+estimateTimeCall.getStart_latitude().toString()+"&start_longitude="+estimateTimeCall.getStart_longitude().toString()+"&product_id="+estimateTimeCall.getProduct_id();
        }
        //Header Set
        HttpHeaders requestHeaders=getHeader(empid);
         //Do Request
         HttpEntity requestEntity=new HttpEntity(requestHeaders);
         ResponseEntity<EstimateTimeResult> response=restTemplate.exchange(URL,HttpMethod.GET,requestEntity,EstimateTimeResult.class);  
         org.springframework.http.HttpStatus statusCode=response.getStatusCode();            
         if(statusCode.value()==422){
             return "Required start latitude,longitude";
         }
         return  response.getBody();                    
    }

4 个答案:

答案 0 :(得分:5)

简单:在Java中不可能(除非您将返回类型更改为Object,但这是非常糟糕的做法)。但是,&#34;不推荐&#34;将是更好的术语。

当然,你可以做这样的事情

class RequestResult {
  static enum Result { PASS, FAIL };
  private Whatever dataForPass;
  private SomethingElse dataForFail;

  Whatever get(){
    return get((dataForFail)->throw new RequestError(dataForFail));
  }

  Whatever get(ErrorHandler handler){
    if(dataForFail != null){
      return handler.handle(dataForFail);
    }
    return dataForPass;
  }
}

interface ErrorHandler{
   Whatever handle(SomethingElse dataForFail) throws RequestError;
}

class RequestError extends RuntimeException{
    SomethingElse data;
    RequestError(SomethingElse data){
         this.data=data;
    }
}

然后您可以让RequestResult处理如何获取Whatever / SomethingElse数据,例如:

Whatever data = result.get((dataForFail) -> ...);
//or throws a RequestError if `SomethingElse` presented.
Whatever data = result.get(); 

然后创建这样一个对象;并根据具有所需数据的对象的实际结果设置。通过这样做,该方法的返回类型可以是RequestResult;你可以用它来传递和失败的请求。但这不是标准做法&#34;。

相反:您只在方法通过时返回一些内容。否则,您将抛出一个适当的异常,其中包含调用者需要提供有用错误消息的信息。

换句话说:你应该清楚地分开&#34; happy&#34;和不快乐的#34;路径。在Java中,你可以通过在出现问题时抛出异常来做到这一点。

答案 1 :(得分:1)

声称这在Java中是不可能的:虽然字面意思是不可能的,但是存在安全地执行此操作的库,受到来自其他编程语言的相同安全接口的启发。

我的快速浏览中最有希望的一个是@palatable's lambda,它将这个想法定义为:

public abstract class Either<L, R> {
    private Either () {}
    // how you make these
    public static <L, R> Either<L, R> left(L l) {  return new Left<>(l); }
    public static <L, R> Either<L, R> right(R r) { return new Right<>(r); }
    // how to use these
    public abstract <V> V match(Function<? super L, ? extends V> leftFn, 
                                Function<? super R, ? extends V> rightFn);

    /* ~ some convenience methods to have a common interface to handle these things ~ */

    // the actual classes
    private static final class Left<L, R> extends Either<L, R> {
        private final L l;
        private Left(L l) {
            this.l = l;
        }

        @Override
        public <V> V match(Function<? super L, ? extends V> leftFn, 
                           Function<? super R, ? extends V> rightFn) {
            return leftFn.apply(l);
        }

        /* some other functions to get .equals() working right etc. */
    }
    // same for Right but with "R" swapped for "L"
}

定义一次后,您可以将实际的返回类型设置为Either <String, ResponseBody>,然后可以return Either.left("hey, it's a string")return Either.right(response.getBody()),然后您可以将这两种类型作为数据处理。

正如许多其他人所注意到的,处理Either <String, x>类型的另一种方法是作为例外,它打破了正常的应用程序逻辑流程;你甚至可以定义一个更普遍的例外。但请记住,这将跳过您可能想要为这两者做的任何常见逻辑。您需要决定在您想要对响应正文做什么与错误String之间是否存在任何共享应用程序逻辑,或者您是否希望拥有此类goto }语句,直接跳转到指定的catch块。对于不同的应用,这些答案可能不同。

答案 2 :(得分:0)

我认为您的问题中的这个应该是JAX-RS REST服务。

所以我想要表明我做这些事情的方式,我不能说是正确的要么完美。

在REST服务中,我返回一个像这样的对象

class APIResponse {
  private Object content = null;
  private Integer code = null;
  private String message = null;
  ... getter, setter and what else
}

APIResponse是REST端点返回的公共对象:

  public Response questionIdGet(String id, SecurityContext securityContext)
  {
    StatusCode sc;
    try {
      sc = new APIResponse().content(surveyBuilder.getQuestionById(id)).code(200);
      return Response.ok()
          .entity(sc)
          .build();
    } catch (Exception e) {
      return Response.status(500)
         .entity(new APIResponse().content(e).code(200).message(e.getMessage()))
          .build();
    }
  }

通过这种方式,您的REST客户端会收到一个公共对象,他们知道在哪里找到内容{ "content" : object }并检查其是否有效{ "status" : 200, "message" : "error..." }

答案 3 :(得分:0)

将其包装到一个处理两者的对象中,或者为错误状态抛出异常并处理它。

毕竟422是你的错误条件,所以抛出异常