符合 SonarQube 的解决方案,增加单元格值

SonarQube-compliant solution, increment cell value

我正在使用 Apache POI 创建一个 excel 形式的 Java POJO class。

POJO 有 65 个字段需要在创建 POJO 时填充。

我想到的一种方法是 -

int i = 0;
hssfRow.createCell(i++).setCellValue(POJO.getField1());
hssfRow.createCell(i++).setCellValue(POJO.getField2());
hssfRow.createCell(i++).setCellValue(POJO.getField3());
.....
hssfRow.createCell(i++).setCellValue(POJO.getField65());

上述方法的缺点是 SonarQube 说它不符合以下原因

Extract this increment or decrement operator into a dedicated statement

第一个问题是这里为什么不建议使用i++

此外,是否建议在单独的常量 class 中声明从 1 到 65 的常量并使用它代替 i++(即 hssfRow.createCell(Constant.ONE))?

除了这个解决方案之外,还有其他更合规且更好的方法吗?

恕我直言,您可以将其标记为误报。该问题的 stated reasons

  • 它会严重影响代码的可读性。
  • 它在语句中引入了额外的副作用,可能会出现未定义的行为。
  • 将这些运算符与任何其他算术运算符分开使用会更安全。

鉴于您当前代码的情况,我认为它们是无效的。代码是完全可读的,没有未定义的行为,我没有看到任何安全问题。

我可以这样:

private static final Map<Integer, Function<POJO, TypeOfCellValue>> cellDataProviders = new HashMap<>(); 
static{
    cellDataProviders.put(1, POJO -> POJO.getField1());
    cellDataProviders.put(2, POJO -> POJO.getField2());
   ...
}

并在代码中使用:

IntStream.range(1, cellDataProviders.size()).foreach( i -> hssfRow.createCell(i).setCellValue(cellDataProviders.get(i).apply(POJO)));

或使用传统的 for 循环:

for(int i = 0; i < cellDataProviders.size(); i++){
     hssfRow.createCell(i).setCellValue(cellDataProviders.get(i).apply(POJO));
}

从POJO到cell的映射已经和数据填充代码分离了。

因为它是误报,您可以使用 @SuppressWarnings("squid:S...")//NOSONAR:

//NOSONAR
hssfRow.createCell(i++).setCellValue(POJO.getField1());
//NOSONAR
hssfRow.createCell(i++).setCellValue(POJO.getField2());
//NOSONAR
hssfRow.createCell(i++).setCellValue(POJO.getField3());
...

然而,将代码从动地更改为更清楚:

hssfRow.createCell(i).setCellValue(POJO.getField1()); ++i;
hssfRow.createCell(i).setCellValue(POJO.getField2()); ++i;
hssfRow.createCell(i).setCellValue(POJO.getField3()); ++i;
...

不疼。


游戏时间

可以使用可变参数方法隐藏索引。 假设POJO对象变量为pojo及其classPojo.

fillCells(hssfRow, pojo,
                Pojo::getField1,
                Pojo::getField2,
                p -> createDateCellValue(p.getField2()),
                Pojo::getField4,
                Pojo::getField5,
                p -> f(pojo),
                Pojo::getField7):

void fillCells(Row hssfRow, Pojo pojo, Function<Pojo, CellValue>... cellProviders) {
    for (int i = 0; i < cellProviders.length; ++i) {
        hssfRow.createCell(i).setCellValue(cellProviders[i].apply(pojo));
    }
}

这不是那么灵活,但会删除一些重复的内容 hssfRow.createCell