在路上

 找回密码
 立即注册
在路上 站点首页 学习 查看内容

使用google protobuf遇到一个的小坑

2016-12-16 12:53| 发布者: zhangjf| 查看: 520| 评论: 0

摘要: 公司使用protobuf,一个同事这样的写法proto文件格式:message PlayerFightQueue { optional int32 fightQueueId = 1; repeated CurArmy curArmy = 2;}复制代码使用的时 ...

公司使用protobuf,一个同事这样的写法
proto文件格式:

  1. message PlayerFightQueue {
  2. optional int32 fightQueueId = 1;
  3. repeated CurArmy curArmy = 2;
  4. }
复制代码

使用的时候:

  1. PlayerFightQueue.Builder fightQueue= getPlayerFightQueue();
  2. List<CurArmy> armies = fightQueue.getCurArmyList();
  3. 这时候armies拿到的是一个java.util.Collections.unmodifiableList
复制代码

要是改成这样:

  1. PlayerFightQueue.Builder fightQueue= getPlayerFightQueue();
  2. fightQueue.getCurArmyBuilderList();
  3. List<CurArmy> armies = fightQueue.getCurArmyList();
  4. 这时候armies拿到的是一个RepeatedFieldBuilder.list
复制代码

为什么会出现这种情况呢?
读了源码才知道protobuf是这样处理的:

  1. public java.util.List<com.wl.protocol.rpc.msg.CurArmyMsg.CurArmy> getCurArmyList() {
  2. if (curArmyBuilder_ == null) {
  3. return java.util.Collections.unmodifiableList(curArmy_);
  4. } else {
  5. return curArmyBuilder_.getMessageList();
  6. }
  7. }
复制代码

这里发现只要curArmyBuilder_ == null才会进行包装,要不调用的是curArmyBuilder_.getMessageList()
那么curArmyBuilder_ 是什么时候变成不为null呢?
继续看代码:

  1. public java.util.List<com.wl.protocol.rpc.msg.CurArmyMsg.CurArmy.Builder>
  2. getCurArmyBuilderList() {
  3. return getCurArmyFieldBuilder().getBuilderList();
  4. }
  5. private com.google.protobuf.RepeatedFieldBuilder<
  6. com.wl.protocol.rpc.msg.CurArmyMsg.CurArmy, com.wl.protocol.rpc.msg.CurArmyMsg.CurArmy.Builder, com.wl.protocol.rpc.msg.CurArmyMsg.CurArmyOrBuilder>
  7. getCurArmyFieldBuilder() {
  8. if (curArmyBuilder_ == null) {
  9. curArmyBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
  10. com.wl.protocol.rpc.msg.CurArmyMsg.CurArmy, com.wl.protocol.rpc.msg.CurArmyMsg.CurArmy.Builder, com.wl.protocol.rpc.msg.CurArmyMsg.CurArmyOrBuilder>(
  11. curArmy_,
  12. ((bitField0_ & 0x00000080) == 0x00000080),
  13. getParentForChildren(),
  14. isClean());
  15. curArmy_ = null;
  16. }
  17. return curArmyBuilder_;
  18. }
复制代码

发现只要是调用了builder方法会改变curArmyBuilder_ 而curArmy_就会被变成null

遇到这种情况还是不要偷懒,老老实实的深复制吧,也许就会出现埋点很深的坑

最新评论

小黑屋|在路上 ( 蜀ICP备15035742号-1 

;

GMT+8, 2025-7-7 18:42

Copyright 2015-2025 djqfx

返回顶部