当前位置: 首页 > 知识库问答 >
问题:

Google Protobuf句柄空值

苏硕
2023-03-14

有人告诉我如何在google protobuf中处理空值<我有这样的结构:

syntax = "proto3";
import "google/protobuf/wrappers.proto";
message Person {
  google.protobuf.DoubleValue age = 4;
}     

和java代码:

DoubleValue myAge = null;
Person build = Person.newBuilder()
                .setAge(myAge)  // <- NPE
                .build();

此代码在. setAGE(myAGE)行上导致空指针异常。
那么原型DoubleValue的用例是什么?我以为它用于管理空值。但仍然收到NullPointerException。

您是否使用这样的代码来处理此问题?

DoubleValue a = null;
Person.Builder builder = Person.newBuilder();
if (a != null) {
    builder.setAge(a);
}

Person build = builder.build();     

更新:
这是protoc命令生成的部分代码:

/**
* <code>.google.protobuf.DoubleValue age = 9;</code>
*/
public Builder setAge(com.google.protobuf.DoubleValue value) {
if (ageBuilder_ == null) {
    if (value == null) {        //<-- Additional statement
        throw new NullPointerException();
    }
    age_ = value;
    onChanged();
} else {
    ageBuilder_.setMessage(value);
}   

为什么在生成的代码中设置额外的if语句<我认为这是google协议缓冲区的一个bug
最后,我编写了以下代码:

DoubleValue.Builder builder = DoubleValue.newBuilder();
DoubleValue myAge = null;
Person build = Person.newBuilder()
                .setAge(myAge != null ? myAge : builder )
                .build();

共有1个答案

宰父玄天
2023-03-14

DoubleValue旨在处理缺失的值,不一定null。pro buf库旨在永远不涉及null-例如,它永远不会返回null,即使是缺失的字段。此外,正如您所发现的,setter不接受null。例如,要清除字段,您可以使用clearField而不是setField(null)

proto2和proto3之间的一个重大区别是(最初)删除了原语字段(例如hasField)的“hazzers”。也就是说,如果您有一个“double my\u”字段,则无法判断它是否从未设置,或是否显式设置为零getMyField()在这两种情况下都将返回0。

请注意,消息仍然有HAZZER,因此如果需要该功能,可以将基本字段包装在消息中。这正是DoubleValue的含义。因此,如果您有一个字段“DoubleValue age=1”,则可以使用“hasAge()”来确定是否已设置该字段。在较新的protobuf版本中,您可以对可选的double age=1执行相同的操作。

请注意,所有这些都与Java生成代码中的null无关。设置者确实不可能接受空值。

太长别读了:你的第一个建议很好而且很常见:

DoubleValue a = null;
Person.Builder builder = Person.newBuilder();
if (a != null) {
    builder.setAge(a);
}
Person build = builder.build();     

如果不是空值,而是可选的,则可以使用类似的变体:

OptionalDouble a = OptionalDouble.empty();
Person.Builder builder = Person.newBuilder();
a.ifPresent(value-> builder.getAgeBuilder().setValue(value));

Person build = builder.build();
 类似资料:
  • 在书写代码与阅读代码的时候,经常会看到这一句代码: typedef void *HANDLE ,它是何方神圣呢?如何理解呢? 不理解它的时候,感觉它很神奇,知道它以后,它就是个typedef的定义,只不过是void*类型罢了,也就是HANDLE等价于void *,我们可以叫它披着句柄皮的指针(PS:指针和句柄是有区别的,在这说句废话); 对于void* 神通广大,因为它作为函数参数or函数返回值,

  • 当你用作图命令时,MATLAB用多种图形对象创建图形,例如线,文本,表面(完整列表见Graphics Objects)。所有图形对象都有控制其性能的属性。你可以在MATLAB中询问每种属性的取值并设置大部分的属性值。 每当MATLAB创建一个图形对象时,它就给该对象赋以一个标识符(称为句柄)。可以用此句柄访问对象属性。若你想作下列操作,句柄图形很有用。 修改图形外观。 通过编写能直接创建和操作对象

  • 问题内容: 我正在尝试自己学习编程,但仍在尝试掌握它。我收到以下错误: java.io.IOException:句柄无效 这是我的代码 我相信,每当我调用该方法时,都会出现错误,当我尝试显示默认构造函数中的字节数时,它可以很好地工作并显示。 问题答案: 好了,在实际开始使用它之前,请先关闭构造函数的块。将结束部分从构造函数中移到完成后将被调用的位置,例如在main 下方调用或单独的close方法。

  • 你可以创建任何MATLAB函数的句柄,然后用这些句柄作为函数链接的途径。函数句柄主要用来传递自变量列表给其他函数,用句柄执行函数或求值。 在MATLAB中,通过在函数名前加上符号@构造函数句柄。下面例子为SIN函数创建一个函数句柄,然后赋值给变量fhandle: fhandle = @sin; 用MATLAB的fevel函数对函数句柄求值。下面的plot_fhandle函数接收一个函数句柄和数据

  • 我使用Spring boot 1.5.7 我还没有配置CommonMultipartResolver,因为Spring Boot已经处理了文件上传。 如果我的上载超过允许的最大大小,则会抛出一个丑陋的异常。 这由我的控制器处理。 这种处理不仅复杂,而且很遗憾是特定于Tomcat的,因为SizeLimitExceededException位于包。 我如何处理这种错误情况,即无论使用哪个Servlet

  • 我正在使用Spring WebFlux webclient进行REST调用。我将连接超时配置为毫秒,相应地: 方法将为每个/响应代码返回一个空的。如何对连接超时甚至读/写超时进行相同的操作。目前,它只是抛出一个,而不处理该异常