0

我只是想知道以下是否是 Optional 的错误用例。可能是,因为它看起来很讨厌。

(这是关于调用返回空值的“传统”代码。)

  private static class Person {
    private Address address;
    private String name;
  }

  private static class Address {
    private Integer housenr;
    private String houseletter;
    private String street;
  }

  public String getAddress(Person person) {
    return Optional.ofNullable(person.getAddress())
      .map(x -> Optional.ofNullable(x.getHousenr()).map(y -> y + " ").orElse("") +
          Optional.ofNullable(x.getHouseletter()).map(y -> y + " ").orElse("") +
          Optional.ofNullable(x.getStreet()).orElse(""))
      .orElse("<unknown>");
  }

  // unit test if string representation of an address is properly generated
  assertThat(getAddress(charlesBabbage))
      .isEqualTo("4 l Regentstreet");

我可能应该将代码放在 Person 类和 Address 类的方法中,这样就不会太困扰我了。

或者我应该用“旧方式”来做:

  public String getAddress(Person person) {
    if (person.getAddress() == null) {
      return "<unknown>";
    }
    StringBuilder builder = new StringBuilder();
    if (person.getAddress().getHousenr() != null) {
      builder.append(person.getAddress().getHousenr() + " ");
    }
    if (person.getAddress().getHouseletter() != null) {
      builder.append(person.getAddress().getHouseletter() + " ");
    }
    if (person.getAddress().getStreet() != null) {
      builder.append(person.getAddress().getStreet() + " ");
    }
    return builder.toString();
  }

请记住,这只是一个示例。可以添加更多字段,例如词缀、邮局、城镇/城市、自治市、州、国家(更不用说外国地址),从而加剧问题。

4

2 回答 2

1

在您的两个示例中,您都在重复代码,在将元素添加到字符串之前检查元素是否为空。您可以通过使用 Stream 和加入来减少这种重复性工作:

public String getAddress(Person person) {
    return Optional.ofNullable(person.getAddress())
            .map(x -> Stream.of(x.getHousenr(), x.getHouseletter(), x.getStreet())
                        .filter(Objects::nonNull)
                        .map(Object::toString)
                        .collect(Collectors.joining(" "))
            )
            .orElse("<unknown>");
}

或者类似地没有可选:

public String getAddress(Person person) {
    Address address = person.getAddress();
    if (address == null) {
        return "<unknown>";
    }
    return Stream.of(address.getHousenr(), address.getHouseletter(), address.getStreet())
            .filter(Objects::nonNull)
            .map(Object::toString)
            .collect(Collectors.joining(" "))
}
于 2021-01-14T10:51:42.077 回答
0

我根本不相信这是错误的用例。的确,如果不考虑格式和空白,阅读起来并不容易,但你使用的方式 Optional对我来说似乎很好。

为了断言,拥有那个(真正丑陋的)代码很好。我不知道您最终的预期用例,但假设您只想生成这些对象的字符串表示,我将在toString()方法或类似方法中封装检查相应类中是否存在空值的逻辑。

编辑:令人讨厌的代码不会使其使用错误。虽然你的同事最终可能会恨你

于 2021-01-08T15:47:53.243 回答