在使用 Jackson 时,我应该使用包装器还是原始类型作为字段

Should I use a wrapper or primitive type as field while using Jackson

我正在使用 Jackson JSON 解析器。我有一个简单的数据传输对象,应该通过 REST 服务返回。

public class PersonDto {

  private String name;
  private Integer age; // int?

  public PersonDto(String name, Integer age) {
      this.name = name;
      this.age = age;
  }

  public String getName() {
      return this.name;
  }

  public Integer getAge() {
      return this.age;
  }
}

在这种情况下,我是否应该支持包装器 类 而不是原始类型作为字段?除了 wrapper 可以为 nullable 之外,这些方法中哪种方法更有优势?

包装器class:java.lang.Integer

优点:

  • 允许 null 值,因此给用户留下空白/未指定字段的机会
  • 当值在 -128 到 127 之间时速度很快,因为它使用其内部缓存而不是创建新对象

  • Integer::valueOf 用于解析 String

缺点:

  • 不可变:如果您必须重置该值(例如:因为它超出了某个范围),您将不得不重新创建一个全新的 Integer 实例。

  • 计算性能较慢

  • java.lang.Integer 是对实例的引用。每次计算都会重新创建一个全新的对象


原始类型:int

优点:

  • 可变(只要非final,并且提供setter):轻松允许:this.age = age > MAX_AGE ? blabla : age;

  • 基本类型计算速度更快

  • Integer::parseInt 用于解析 String

缺点:

  • 非selected 值将自动设置为 0;这可能会混淆用户是否 selected 0 作为值,或者没有 select 任何东西

似乎 java.lang.Integer 的唯一优势是 blank / null 值。

此外,在需要包装器的情况下,例如:

List<Integer> myList;

您可以直接添加一个未装箱的值 myList.add(2);,编译器会将其解释为 myList.add(Integer.valueOf(2));

我发现在 DTO 中使用包装器很有用。使用 Jackson,对于 nullable fields,您可以在 DTO 对象之上设置 @JsonInclude(JsonInclude.Include.NON_NULL) 并减少数据数量通过网络发送(结果 JSON 中不会出现空字段),从而解决值为 0 或不存在时的歧义,告诉前端不存在节点,因此没有 processing/displaying 数据需要。 对于不可为 null 的数字数据,primitive 效果很好。 此外,对于算术计算中不应在前端使用的浮点数据,可以使用在服务器端进行舍入的 String。我在 REST API 中多次看到这种技术。

    DecimalFormat df = new DecimalFormat("#.####");
    df.setRoundingMode(RoundingMode.CEILING);
    System.out.println(df.format(d));