来自 PMD 的 Java 流 while 循环异常警告
Posted
技术标签:
【中文标题】来自 PMD 的 Java 流 while 循环异常警告【英文标题】:Java stream while loop anomaly warnings from PMD 【发布时间】:2020-10-08 05:56:51 【问题描述】:在下面的代码中,我创建了一个新的 ID,检查它是否存在,如果它是唯一的则返回它:
private String generateNewId(List<Item> items)
do
String newId = ... // generateNewId from another method
if (items.stream.noneMatch(i -> i.getId().equals(newId)))
return newId;
while(true);
但是,我遇到了 PMD 异常:
发现变量“newId”的“DD”异常 发现变量“newId”的“DU”异常来自 PMD 文档:
DU - 异常:最近定义的变量未定义。这些 异常可能出现在正常的源文本中。 DD - 异常:A 最近 定义的变量被重新定义。这是不祥之兆,但不一定是 错误。
我尝试将 newId
变量移到循环外,但随后出现错误:lambda 中使用的变量应该是最终的或有效的最终。
如何重构代码以消除这些异常?或者我应该将这些警告视为误报吗?
【问题讨论】:
与问题无关,但您不应生成这样的 ID。您拥有的项目越多,所需的时间就越长(生成 n 个 ID 需要 O(n^2) 步)。您应该使用 UUID,这在技术上并不能避免 ID 冲突,但它们太不可能了,所以没关系。 @***soft 我知道,不幸的是,这是客户端的要求之一——保持向后兼容性。我更喜欢使用 UUID,我就是不能...... 【参考方案1】:您看到了 DD 异常,因为当 if 条件评估为 false 时,变量 newId
在 do while(true)
循环中被重新定义。
然而,我认为 DU 异常是误报。在这种情况下,newId
总是至少使用一次:
newId
如果项目列表不为空,则在nonMatch
的闭包中使用newId
但这是 PMD 无法弄清楚的,因为它不知道 noneMatch
的语义。如果您将 noneMatch
替换为 anyMatch
,那么这将是真正的 DU 异常。
DD 和 DU 异常通常很难修复,因为它们指出了更高级别的设计问题。在这种情况下,问题不直接在于变量 newId
本身,而是使用 do while(true)
可能导致无限循环,因为您忽略了无法生成新唯一 ID 的情况。
解决此问题的一种方法是解决此问题:
private String generateNewId(List<Item> items)
return Stream.generate(this::getRandomId)
.limit(100)
.filter(id -> isNew(id, items))
.findAny()
.orElseThrow(() -> new NoSuchElementException("Failed to generate unique id."));
private String getRandomId()
return "4"; // chosen by fair dice roll.
// guaranteed to be random.
private boolean isNew(String id, List<Item> items)
return items.stream().noneMatch(item -> id.equals(item.getId()));
此解决方案通过尝试生成新的 id 最多 100 次来解决无限循环问题,如果失败则抛出异常。根据您的情况,您可能会选择不同的限制。
【讨论】:
以上是关于来自 PMD 的 Java 流 while 循环异常警告的主要内容,如果未能解决你的问题,请参考以下文章
来自 pmd:DataflowAnomalyAnalysis sslContext 的 Java UR-anomaly 和 DR-anomaly
Java代码PMD抱怨Cyclomatic Complexity,20