You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ChronicleWire实体可选字段使用报错,应如何正确实现?

问题原因说明
  1. 直接声明可空Marshallable类型字段报错:2.22ae6版本ChronicleWire默认自动生成的序列化逻辑不会对Marshallable类型字段做空值检查,会直接调用该字段的序列化方法,空值触发NPE。
  2. 使用java.util.Optional报错:该版本原生不支持JDK Optional作为字段类型,序列化器仅支持Marshallable实现类、字符串、装箱基础类型三类字段。
  3. 自定义OptionalValue报错:存在三个问题:
    • write方法中空值写入方法拼写错误,把null()写为了nu11()(数字1替代了字母l)
    • Lombok的@NoArgsConstructor(staticName = "empty")会将无参构造器设为私有,序列化反射实例化时找不到公共无参构造,转而尝试查找String参数构造器失败
    • 反序列化逻辑错误,非空值读取时未先实例化泛型对象,直接为null的value属性赋值
修复方案

方案1:直接重写实体的序列化/反序列化方法(最简方案)

不需要额外封装可选类型,直接在实体类中手动处理可空字段即可:

public class Foo extends SelfDescribingMarshallable {
  private String name;
  private Baz baz;

  @Override
  public void writeMarshallable(@NotNull WireOut wire) {
    wire.write("name").text(name);
    if (baz == null) {
      wire.write("baz").null();
    } else {
      wire.write("baz").marshallable(baz);
    }
  }

  @Override
  public void readMarshallable(@NotNull WireIn wire) {
    this.name = wire.read("name").text();
    var bazVal = wire.read("baz");
    if (!bazVal.isNull()) {
      this.baz = new Baz();
      bazVal.marshallable(this.baz);
    } else {
      this.baz = null;
    }
  }
}

方案2:修复自定义OptionalValue实现

如果需要通用可选类型封装,修复原有代码的问题即可:

import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import net.openhft.chronicle.core.util.ObjectUtils;
import net.openhft.chronicle.wire.Marshallable;
import net.openhft.chronicle.wire.WireIn;
import net.openhft.chronicle.wire.WireOut;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.ParameterizedType;

@AllArgsConstructor(staticName = "of")
@NoArgsConstructor
public class OptionalValue<T extends Marshallable> implements Marshallable {
    @Nullable
    private T value;

    @Override
    public void readMarshallable(@NotNull WireIn wire) {
        var val = wire.read("value");
        if (!val.isNull()) {
            Class<T> clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
            value = ObjectUtils.newInstance(clazz);
            val.marshallable(value);
        } else {
            value = null;
        }
    }

    @Override
    public void writeMarshallable(@NotNull WireOut wire) {
        if (value == null) {
            wire.write("value").null();
        } else {
            wire.write("value").marshallable(value);
        }
    }

    public boolean isEmpty() {
        return value == null;
    }

    public T get() {
        return value;
    }

    public static <T extends Marshallable> OptionalValue<T> empty() {
        return new OptionalValue<>();
    }
}

内容的提问来源于stack exchange,提问作者rvit34

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 04:15:02