【问题标题】:The return value of "putIfAbsent" must be used - really?必须使用“putIfAbsent”的返回值——真的吗?
【发布时间】:2019-02-27 20:17:50
【问题描述】:

我有一个像这样的 ConcurrentMaps 的 ConcurrentMap...

ConcurrentMap<String, ConcurrentMap<K, V>> mapsMap = new ConcurrentHashMap<>();

现在,在某些方法中,我想通过确保存在这样的某个键的映射来防止 NPE...

 mapsMap.putIfAbsent(someKey, new ConcurrentHashMap<K, V>());

...所以我可以安全地调用...

 mapsMap.get(someKey).put(...);

...这里不用担心空值。

现在,Sonarqube 告诉我,这违反了规则 RSPEC-2201...

不应忽略来自没有副作用的函数的返回值 [..] 以及 ConcurrentMap.putIfAbsent 调用忽略的返回值。

这只是 SonarQube 没有检测到该方法的副作用对我来说已经足够了(并且返回值不会添加任何信息)还是我错过了关于 putIfAbsent 合约的重要一点?

【问题讨论】:

  • 如果您的示例中最后两个 sn-ps 相互跟随,请执行此操作 mapsMap.putIfAbsent(someKey, new ConcurrentHashMap&lt;K, V&gt;()).put(aValue)
  • 我确实想知道他们在想什么。同样奇怪的是,他们只对 ConcurrentHashMap.putIfAbsent 这样做——而不是 Map.putIfAbsent,它具有相同的合同。
  • @yshavit 同意。它可能与并发有关。但是哪一个? :)
  • @davidxxx 这对我来说没有任何意义,所以很难说。 :-) 这也很奇怪,因为他们的文档说 RSPEC-2201 是关于“没有副作用的函数”,并且 put 肯定有副作用。我可能会忽略一些东西,但我实际上怀疑这只是这方面的一个违规规则。
  • @Florian Schaetz 有道理,你的意图是好的:如果我们得到他们的回答,它很可能会帮助其他人。

标签: java sonarqube


【解决方案1】:

如果指定的键尚未与值关联(或 映射到 null) 将其与给定值关联并返回 null, else 返回当前值。

如果您不需要返回值,您可以放心地忽略它。
Sonarqube 对某些规则非常具有侵入性,因此只需禁用它并继续您的业务。

恕我直言,该特定规则主要是针对由多个开发人员编写代码的项目中的常见模式设置的。

【讨论】:

  • 我担心的是,明确使用ConcurrentMap 的规则似乎非常具体,所以我担心这里有一些“隐藏”的原因。不幸的是,我不想禁用该规则,因为对于许多其他情况,它完全有意义,例如,在不关心结果的情况下调用 "someString".toUpperCase() 很可能是一个错误。关于ConcurrentMap 的部分不清楚(甚至是错误的?)。
  • @FlorianSchaetz 我的意思是针对特定情况禁用它,这对我来说没有意义。老实说,我知道没有隐藏的原因。您只是在使用 Map 接口的同步实现,但产生的结果与尊重 Map 契约的所有其他实现相同。
  • 同意第一部分,但是“恕我直言,该特定规则主要针对由多个开发人员编写代码的项目中的常见模式设置”是什么意思。 ?从事项目的开发人员数量不会对运行时的潜在错误/问题产生影响。
  • @davidxxx 许多 Sonarqube 规则用于为开发人员设置编码标准。有时这些规则可以,有时则不行。规则本身是可以的,但这个用例如果有缺陷
【解决方案2】:

除了@LppEdd 的正确分析器之外,这个问题也在声纳论坛上answered 结束:

基本上,这条规则取自 FindBugs 的规则RV_RETURN_VALUE_OF_PUTIFABSENT_IGNORED

putIfAbsent 方法通常用于确保单个值 与给定键相关联(第一个值 put if 缺席成功)。如果您忽略返回值并保留一个 引用传入的值,您冒着保留一个 不是与映射中的键关联的值。 如果重要的是您使用哪一个并且使用未存储的那个 在地图中,您的程序将出现错误的行为。

在这种情况下,我不保留对存储值的引用,这确实是误报。

此特定规则可能会在未来作为单独的规则在 SonarQube 中实施,而不是作为当前规则 (RSPEC-2201) 的一部分。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-07
    • 1970-01-01
    • 2012-05-14
    • 1970-01-01
    • 2021-05-14
    • 2014-04-15
    • 2016-03-15
    • 2010-09-16
    相关资源
    最近更新 更多