公司使用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
遇到这种情况还是不要偷懒,老老实实的深复制吧,也许就会出现埋点很深的坑 |