正常情况下,在Java中入参是不建议用做返回值的。除了造成代码不易理解、语义不清等问题外,可能还埋下了陷阱等你入坑。

问题背景

比如有这么一段代码:

上面代码,服务A希望调用服务B,以获取supplyList,但同时,服务A又希望修改localSupply的状态值,未能避免修改calcSupplyAssignment接口的(不想改返回的类型),将localSupply作为了入参但同时也用作了返回值。

服务B代码如下:

在服务B代码内部,服务A的入参localSupply被传入,希望重新被supplyAssignment赋值而后返回新值。然而,这样做是无效的。

问题原因

先来看下编程语言中关于参数传递的类型:值传递(pass by value)是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

引用传递(pass by reference)是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

因为Java程序设计语言是采用的值传递,因为Java没有指针的概念。也就是说方法得到的是所有参数值的一个拷贝,方法并不能修改传递给它的任何参数变量的内容。

因此,上述代码中,服务A调用服务B时,服务B的参数localSupply实际上是服务A的localSupply的一个拷贝,当然,这两个都是指向了同一个地址对象supplyAssignment1。

当在服务B内部对参数localSupply进行重新赋值是localSupply = supplyAssignment,实际上,只是对B的参数localSupply做了从新赋值,B的参数localSupply会指向一个新的地址对象supplyAssignment2。

从上图可以清晰看到,因此,服务A的localSupply和B的参数localSupply已经指向了不同的对象了,对B的参数localSupply做任何的修改,都不会影响服务A的localSupply的原值。这就是问题的原因,你希望服务B来修改服务A入参的状态,并将改后的值返回给服务A,但并不奏效。

解决方案

方案1:入参不要用作返回值

当然,这个是最清晰的且易于理解的,但这会导致有的接口的返回类型产生变化。

有时确实想要入参做返回值,那看方案2。

方案2:入参不要赋值新对象

这个方案就是直接在入参的对象上做状态的修改,而不要去赋值新对象。还是这个图:

在这个图中,只要我们是一直在B的参数localSupply修改的是supplyAssignment1的状态值,那结果就能反馈到服务A的localSupply上。如何实现?看下下面代码:

在上面的方法中,我们用到了Spring的工具类BeanUtils,该类的copyProperties方法的实质是将supplyAssignment的属性值,赋值到了localSupply的属性上。这意味着我们是修改的B的参数localSupply上的属性,而并未新建对象。

作者:码农开花

链接:https://juejin.cn/post/6919701401681526791

来源:掘金

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

java什么时候用有参_Java有陷阱——慎用入参做返回值相关推荐

  1. java值参_Java陷阱之慎用入参做返回值详解

    正常情况下,在Java中入参是不建议用做返回值的.除了造成代码不易理解.语义不清等问题外,可能还埋下了陷阱等你入坑. 问题背景 比如有这么一段代码: @Named public class AServ ...

  2. java 骗局_Java有陷阱,用时需谨慎——慎用入参做返回值

    正常情况下,在Java中入参是不建议用做返回值的.除了造成代码不易理解.语义不清等问题外,可能还埋下了陷阱等你入坑. 问题背景 比如有这么一段代码: @Named public class AServ ...

  3. java 返回值给c_Java有陷阱,用时需谨慎——慎用入参做返回值

    正常情况下,在Java中入参是不建议用做返回值的.除了造成代码不易理解.语义不清等问题外,可能还埋下了陷阱等你入坑. 问题背景 比如有这么一段代码:@Named public class AServi ...

  4. java 返回值判断_在Java中判断方法重载的条件除了参数外,还可以通过返回值类型判断。_学小易找答案...

    [单选题]若int x;且有下面的程序片断,则输出结果是() . for (x=3; x<6; x++) { printf((x%2) ? "##%d" : "** ...

  5. java 内部类 返回值_Java基础第10天+形式参数和返回值的问题、包、导包、权限修饰符、常见的修饰符、内部类(局部内部类,成员内部类,匿名内部类)...

    1:形式参数和返回值的问题(理解) (1)形式参数: 类名:需要该类的对象 抽象类名:需要该类的子类对象 接口名:需要该接口的实现类对象 (2)返回值类型: 类名:返回的是该类的对象 抽象类名:返回的 ...

  6. java try 返回值_JAVA的try... catch finally的return返回值问题

    下面看一个例子(例1),来讲解Java里面中try.catch.finally的处理流程 public class TryCatchFinally { @SuppressWarnings(" ...

  7. oracle 异常返回值,oracle - java.sql.SQLException:无效的列类型:调用具有行类型返回值的函数时为1111 - 堆栈内存溢出...

    我在一个名为" MyPackage"的Oracle软件包中有一个函数: FUNCTION MyFunction(name IN VARCHAR2) RETURN MyTable%r ...

  8. java找不到返回值_java.lang.IllegalArgumentException:找不到类型返回值的转换器

    有了这段代码 @RequestMapping(value = "/bar/foo", method = RequestMethod.GET) public ResponseEnti ...

  9. java递归函数返回值_java基础5(方法、有无返回值、重载、递归)

    方法: 定义:解决事情的办法.具有特定功能的代码块 特点: 1.方法不调用不执行 2.类中方法外,方法不能嵌套 有返回值类型的方法 定义格式: 修饰符 返回值类型 方法名([参数列表]){ 方法体语句 ...

最新文章

  1. R语言ggplot2可视化分面图(facet_grid):去除分面图灰色矩形框以及框中的标签、Getting rid of facet_grid labels on those gray boxes
  2. R语言广义线性模型泊松回归(Poisson Regression)模型
  3. 微服务实践分享(5)缓存中心
  4. SAP BASIS顾问认知的一些误区
  5. CF1200D-White Lines【二维前缀和】
  6. 时间管理----分析工作安排和首要任务
  7. 【Spring】Spring xml 名称和别名
  8. 原生python自带的ide_python自带的IDE是一个功能强大的IDE
  9. Python命令行参数
  10. 电容(2)——电容在电路中的作用
  11. QQ定时发消息vbs代码
  12. PyTorch基础(六)-- optim模块
  13. 每日一题:42. 接雨水
  14. 4.1 随机变量的数学期望
  15. Androidstudio检测不到夜深模拟器解决方法
  16. 一文读懂机器学习,大数据/自然语言处理/算法全有了…… (非常好)
  17. c语言教程+school,C语言教程方法用法 _C语言-w3school教程
  18. 成考期末计算机组成原理,计算机组成原理期末考试试题及答案
  19. ushort mysql,Mysql的CodeFirst:不支持ushort、uint、ulong的字段提示不足
  20. NXP MPC574X PLL配置和问题

热门文章

  1. oracle12c dml语句缓存,Oracle --DML、DDL、DCL
  2. Evaluation and Validation of AssemblingCorrected PacBio Long Reads for MicrobialGenome Completion
  3. Linux指定网卡优先级,如何在Ubuntu中设置网络连接的优先级?
  4. 二十三、斐波那契查找算法
  5. pytorch模型3.13
  6. 人体姿态跟踪--Pose Flow: Efficient Online Pose Tracking
  7. GAN人脸修复--Generative Face Completion
  8. CMAKE支持c99的两种方式
  9. 报错解决:ninja: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by ninja)
  10. java学生-成绩关联实体_java毕业设计_springboot框架的学生成绩智能管理