公司使用protobuf来作为通讯格式,一个同事这样的写法
proto文件格式:
message PlayerFightQueue {
optional int32 fightQueueId = 1;
repeated CurArmy curArmy = 2;
}
使用的时候:
PlayerFightQueue.Builder fightQueue= getPlayerFightQueue();
List<CurArmy> armies = fightQueue.getCurArmyList();
这时候armies拿到的是一个java.util.Collections.unmodifiableList
要是改成这样:
PlayerFightQueue.Builder fightQueue= getPlayerFightQueue();
fightQueue.getCurArmyBuilderList();
List<CurArmy> armies = fightQueue.getCurArmyList();
这时候armies拿到的是一个RepeatedFieldBuilder.list
为什么会出现这种情况呢?
读了源码才知道protobuf是这样处理的:
public java.util.List<com.wl.protocol.rpc.msg.CurArmyMsg.CurArmy> getCurArmyList() {
if (curArmyBuilder_ == null) {
return java.util.Collections.unmodifiableList(curArmy_);
} else {
return curArmyBuilder_.getMessageList();
}
}
这里发现只要curArmyBuilder_ == null才会进行包装,要不调用的是curArmyBuilder_.getMessageList()
那么curArmyBuilder_ 是什么时候变成不为null呢?
继续看代码:
public java.util.List<com.wl.protocol.rpc.msg.CurArmyMsg.CurArmy.Builder>
getCurArmyBuilderList() {
return getCurArmyFieldBuilder().getBuilderList();
}
private com.google.protobuf.RepeatedFieldBuilder<
com.wl.protocol.rpc.msg.CurArmyMsg.CurArmy, com.wl.protocol.rpc.msg.CurArmyMsg.CurArmy.Builder, com.wl.protocol.rpc.msg.CurArmyMsg.CurArmyOrBuilder>
getCurArmyFieldBuilder() {
if (curArmyBuilder_ == null) {
curArmyBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
com.wl.protocol.rpc.msg.CurArmyMsg.CurArmy, com.wl.protocol.rpc.msg.CurArmyMsg.CurArmy.Builder, com.wl.protocol.rpc.msg.CurArmyMsg.CurArmyOrBuilder>(
curArmy_,
((bitField0_ & 0x00000080) == 0x00000080),
getParentForChildren(),
isClean());
curArmy_ = null;
}
return curArmyBuilder_;
}
发现只要是调用了builder方法会改变curArmyBuilder_ 而curArmy_就会被变成null
遇到这种情况还是不要偷懒,老老实实的深复制吧,也许就会出现埋点很深的坑
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。