私はデータベースからデータを取得してprotobuffメッセージを作成するものに取り組んでいます。特定のフィールドのデータベースからnull値を取得できる可能性を考えると、protobuffメッセージを作成しようとするとNull-pointer例外が発生します。スレッドからのプロトバフではnullがサポートされていないことを知る http://code.google.com/p/protobuf/issues/detail?id=57 、他に唯一の方法があるのかスローされるNPEを処理するには、以下のようなプロトタイプに対応するJavaファイルに手動チェックを挿入します!
message ProtoPerson{
optional string firstName = 1;
optional string lastName = 2;
optional string address1 = 3;
}
ProtoPerson.Builder builder = ProtoPerson.Builder.newBuilder();
if (p.getFirstName() != null) builder.setFirstName(p.getFirstName());
if (p.getLastName() != null) builder.setLastName(p.getLastName());
if (p.getAddress1() != null) builder.setAddress1(p.getAddress1());
...
だから誰かが、プロトバフ構築中にnull値を処理する他の可能な効率的な方法があるかどうかを明確にすることができますか?
これには簡単な解決策はありません。 nullチェックを処理することをお勧めします。しかし、本当にそれらを取り除きたい場合は、いくつかのアイデアがあります:
setOrClearFoo()
メソッドを追加する code generatorプラグイン を書くことができます。 Javaコードジェネレーターは、このために 挿入ポイント を提供します(そのページの終わりを参照)。p
のget*()
メソッドを反復処理し、それぞれを呼び出し、null
を確認してから呼び出すことができます。 builder
のset*()
メソッド(null以外)これには、新しいフィールドを追加するたびにコピーコードを更新する必要がないという利点がありますが、各フィールドを明示的にコピーするコードを記述するよりもはるかに遅くなります。免責事項:毎日protobufsを使用してGoogle社員から回答します。私は決してGoogleを代表するものではありません。
Person
またはPersonProto
ではなくProtoPerson
と名前を付けます。コンパイルされたprotobufsは、使用している言語によって指定されたクラス定義であり、いくつかの改善が加えられています。 「Proto」を追加すると、さらに冗長になります。YourMessage.hasYourField()
の代わりにYourMessage.getYourField() != null
を使用します。 protobuf文字列のデフォルト値は空の文字列で、[〜#〜] not [〜#〜]nullと等しくなります。一方、フィールドが設定されていないか、クリアされているか空の文字列であるかに関係なく、.hasYourField()
は常にfalseを返します。一般的なprotobufフィールドタイプの default値 を参照してください。null
にプログラムで設定しないでください。プロトブフ以外でも、null
あらゆる種類の問題を引き起こします 。代わりに.clearYourField()
を使用してください。Person.Builder
_クラスには[〜#〜] not [〜#〜]には.newBuilder()
メソッドがありません。 Person
クラスが行います。 Builderパターンを次のように理解します。新しいビルダーは、まだ作成していない場合にのみ作成します。Protobufの書き換え:
_message Person {
optional firstName = 1;
optional lastName = 2;
optional address1 = 3;
}
_
ロジックの書き換え:
_Person thatPerson = Person.newBuilder()
.setFirstName("Aaa")
.setLastName("Bbb")
.setAddress1("Ccc")
.build();
Person.Builder thisPersonBuilder = Person.newBuilder()
if (thatPerson.hasFirstName()) {
thisPersonBuilder.setFirstName(thatPerson.getFirstName());
}
if (thatPerson.hasLastName()) {
thisPersonBuilder.setLastName(thatPerson.getLastName());
}
if (thatPerson.hasAddress1()) {
thisPersonBuilder.setAddress1(thatPerson.getAddress1());
}
Person thisPerson = thisPersonBuilder.build();
_
thatPerson
が、空の文字列、空のスペース、またはnullの属性値を持つ作成した人物オブジェクトである場合、 GuavaのStrings
library を使用することをお勧めします。
_import static com.google.common.base.Strings.nullToEmpty;
Person.Builder thisPersonBuilder = Person.newBuilder()
if (!nullToEmpty(thatPerson.getFirstName()).trim().isEmpty()) {
thisPersonBuilder.setFirstName(thatPerson.getFirstName());
}
if (!nullToEmpty(thatPerson.hasLastName()).trim().isEmpty()) {
thisPersonBuilder.setLastName(thatPerson.getLastName());
}
if (!nullToEmpty(thatPerson.hasAddress1()).trim().isEmpty()) {
thisPersonBuilder.setAddress1(thatPerson.getAddress1());
}
Person thisPerson = thisPersonBuilder.build();
_