用java写业务逻辑的时候,有时候一个方法可能需要返回多个出参,当中可能有List,String,Map等不同类型的数据结构,针对这种情况,我的解决策略一般是使用Map的形式来解决,具体分析请浏览下文。
1.直接返回map
如下是我最近写的直接用Map来返回多个出参的code piece:
public Result<Map<String,Object>> queryProductListBWNew(ProductParamDTO dto) { Result<Map<String,Object>> result = new Result<Map<String,Object>>(); List<ProductResultDTO> resultList=new LinkedList<ProductResultDTO>(); Double amtRangeMax = Double.MIN_VALUE; Double amtRangeMin = Double.MAX_VALUE; try { Map<String,Object> resultMap = new HashMap<String,Object>(); /** * todo logic code */ resultMap.put("resultList",resultList); resultMap.put("amtRangeMax",amtRangeMax); resultMap.put("amtRangeMin",amtRangeMin); result.setRe(resultMap); result.setStatus(0); }catch(Exception e){ logger.error("筛选产品异常!异常信息: " + e.getStackTrace()); result.setStatus(-1); result.setMsg("系统异常"); return result; } logger.error("获取可贷款产品列表()出参:" + JSON.toJSONString(resultMap)); return result; }
summary:
优点:
1
.解决了出参不能返回多个值的问题。
缺点:
1.需要通过javadoc等方式,获知该方法返回的"key"的名称。
2.不知道Map<>中有多少对<key,value>映射,给人的感觉就像是dos系统下的黑窗口,反参有什么,不清楚,不明确。只能通过文档。
2.封装tuple
(0)Util示例:
public class Tuple<T1 extends Serializable, T2 extends Serializable> implements Serializable { public final T1 a; public final T2 b; public Tuple(T1 a, T2 b) { this.a = a; this.b = b; } }
public class TwoTuple<A, B> { private final A first; private final B second; public TwoTuple(A a, B b) { this.first = a; this.second = b; } public A getFirst() { return this.first; } public B getSecond() { return this.second; } }
public class ThreeTuple<A, B, C> extends TwoTuple<A, B> { private final C third; public ThreeTuple(A a, B b, C c) { super(a, b); this.third = c; } public C getThird() { return this.third; } }
public class FourTuple<A, B, C, D> extends ThreeTuple<A, B, C> { private final D fourth; public FourTuple(A a, B b, C c, D d) { super(a, b, c); this.fourth = d; } public D getFourth() { return this.fourth; } }
public final class TupleUtil { private TupleUtil() { } public static <A, B> TwoTuple<A, B> tuple(A a, B b) { return new TwoTuple(a, b); } public static <A, B, C> ThreeTuple<A, B, C> tuple(A a, B b, C c) { return new ThreeTuple(a, b, c); } public static <A, B, C, D> FourTuple<A, B, C, D> tuple(A a, B b, C c, D d) { return new FourTuple(a, b, c, d); } }
(1)调用示例:
1.tuple设置出参:
private static TwoTuple<List<Image>, Rectangle> getImages(List<String> urls) throws Exception { List<Image> list = new ArrayList<Image>(); float urx = 1191; float ury = 1684; for (String url : urls) { Image image = Image.getInstance(url); image.scalePercent(100); image.setBorder(1); image.setBorderWidth(10); image.setBorderColor(Color.WHITE); if(urx < image.getWidth() || ury < image.getHeight()) { image.scalePercent(getPercent(image.getHeight(), image.getWidth())); } list.add(image); } return TupleUtil.tuple(list, new Rectangle(urx, ury)); }
2.接口调用方
public static Tuple<DealerCreditInfoDTO,DealerCreditInfoRecordDTO> queryDisInfo(String disId) { final Object logsId = LogUtils.initLogsId(); final String desc = "远程获取分销商信息queryDisInfo方法:"; LogUtils.error(logger, logsId, desc + "入参:", disId); Tuple<DealerCreditInfoDTO,DealerCreditInfoRecordDTO> dis = null; try { Result<Tuple<DealerCreditInfoDTO,DealerCreditInfoRecordDTO>> result = (Result<Tuple<DealerCreditInfoDTO,DealerCreditInfoRecordDTO>>)RemoteClientUtils.getDefaultClient().executeToObject(QUERY_DIS_INFO,disId); if(result.getStatus()== RemoteCommConstant.REMOTE_SUCCES_STATUS){ dis= result.getRe(); }else{ LogUtils.error(logger, logsId, desc + "失败原因:", result.getMsg()); } } catch (Exception e) { LogUtils.error(logger, logsId, desc + "异常信息:", e); } return dis; }
summary:(我的公司目前使用的是这种形式)
优点:
1.封装了tuple工具,通过出参个数选用不同的tuple工具,接口方和调用方都通过tuple建立起了规范。
2.对Map形式出参进行了优化,出参的数量确定了。
缺点:
1.没能明确地指出,出参中的key的内容是什么,没有文档,这个服务的调用方是不敢往下写的。
3.Enum
这种方式是我无意间在网上看到的,结合对上述2种形式的思考,发现正好可以解决上述优化前后仍然存在的缺陷。
EnumMap作为返回值类型,自己定义一个enum,将可能返回的属性名定义为enum取值即可
-----------------------------------start--此代码块来自上述网址--start------------------------------------------
接口:
public interface TestService { enum UserInfoProperty { ROOM,CELLPHONE,Name } public EnumMap<UserInfoProperty,Object> getUserInfoByName(String name); }实现:
public class TestServiceImpl implements TestService { @Override public EnumMap<UserInfoProperty, Object> getUserInfoByName(String name) { EnumMap<UserInfoProperty,Object> retMap = new EnumMap<UserInfoProperty, Object>(UserInfoProperty.class); retMap.put(UserInfoProperty.ROOM,"0003"); retMap.put(UserInfoProperty.CELLPHONE,"00004"); retMap.put(UserInfoProperty.Name,name); return retMap; } }
调用:
public class App { public static void main( String[] args ) { TestService testService = new TestServiceImpl(); String name = "testName"; EnumMap<TestService.UserInfoProperty,Object> userInfo = testService.getUserInfoByName(name); userInfo.entrySet().iterator(); System.out.println(userInfo.get(TestService.UserInfoProperty.Name)); System.out.println(userInfo.get(TestService.UserInfoProperty.ROOM)); System.out.println(userInfo.get(TestService.UserInfoProperty.CELLPHONE)); } }
------------------------------------end--此代码块来自上述网址--end--------------------------------------------
summary:
优点:
1.反参可以是多个值。
2.通过枚举(最好定义在base中),同一家公司内部,以此方式作为返回值的服务,基本不用看javadoc或者api文档,就知道出参有哪些了。
总之,自己敲过的代码,多反思怎么能写的更好,再去看看别人怎么写,这样成长的很快。