序列化
1. 序列化的意义
- 含义
-
序列化是把对象的状态信息转化为可存储或者传输的形式的过程,也就是把对象转化为字节序列的过程称为对象的序列化。
-
反序列化是把字节序列恢复为对象的过程称为对象的反序列化
序列化就是把实体对象状态按照一定的格式写入到有序字节流,反序列化就是从有序字节流重建对象,恢复对象状态
- 意义
(1)永久性保存对象,保存对象的字节序列到本地文件或者数据库中;
(2)通过序列化以字节流的形式使对象在网络中进行传递和接收;
(3)通过序列化在进程间传递对象;
- 序列化算法一般会按步骤做如下事情
(1)将对象实例相关的类元数据输出。
(2)递归地输出类的超类描述直到不再有超类。
(3)类元数据完了以后,开始从最顶层的超类开始输出对象实例的实际数据值。
(4)从上至下递归输出实例的数据
2. 优劣指标:
-
序列化后的数据大小
-
序列化操作本省的速度以及系统资源开销:CPU、内存
3. JDK的序列化:
3.1 一个类只要实现了 java.io.Serializable 接口,那就可以被序列化
/**
* @description:
* @date : 2020/1/7 22:56
* @author: zwz
*/
public interface ISerializer {
<T> byte[] serializer(T obj);
<T> T deSerializer(byte[] data, Class<T> clazz);
}
3.2 通过输出流 java.io.ObjectOutputStream 和对象输入流 java.io.ObjectInputStream 来实现
package com.gp.lock.serizlizer;
import java.io.*;
/**
* @description: 基于JDK实现序列化
* @date : 2020/1/7 22:58
* @author: zwz
*/
public class JavaSerializer implements ISerializer {
/**
* 序列化
* 使用输出流
* @param obj
* @param <T>
* @return
*/
public <T> byte[] serializer(T obj) {
ByteArrayOutputStream byteArrayOutputStream = null;
ObjectOutputStream objectOutputStream = null;
try {
byteArrayOutputStream = new ByteArrayOutputStream();
objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(obj);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (objectOutputStream != null) {
objectOutputStream.close();
}
if (byteArrayOutputStream != null) {
byteArrayOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return byteArrayOutputStream.toByteArray();
}
/**
* 反序列化
* 使用输入流
* @param data
* @param clazz
* @param <T>
* @return
*/
public <T> T deSerializer(byte[] data, Class<T> clazz) {
ByteArrayInputStream byteArrayInputStream = null;
ObjectInputStream objectInputStream = null;
Object result = null;
try {
byteArrayInputStream = new ByteArrayInputStream(data);
objectInputStream = new ObjectInputStream(byteArrayInputStream);
result = objectInputStream.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (byteArrayInputStream != null) {
byteArrayInputStream.close();
}
if (objectInputStream != null) {
objectInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return (T) result;
}
}
3.3 实例
package com.gp.lock.serizlizer;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Arrays;
/**
* @description:
* @date : 2020/1/7 23:11
* @author: zwz
*/
public class User /*extends SuperClass*/ implements Serializable {
private static final long serialVersionUID = 6322539910270175988L;
public static int num = 5;
private String name;
private int age;
private transient String hobby;
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public static int getNum() {
return num;
}
public static void setNum(int num) {
User.num = num;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", hobby='" + hobby + '\'' +
'}';
}
private void writeObject(ObjectOutputStream outputStream) throws IOException {
outputStream.defaultWriteObject();
outputStream.writeObject(hobby);
}
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
inputStream.defaultReadObject();
hobby = (String) inputStream.readObject();
}
public static void main(String[] args) {
ISerializer serializer = new JavaSerializer();
User user = new User();
user.setAge(18);
user.setName("mic");
byte[] bytes = serializer.serializer(user);
System.out.println(Arrays.toString(bytes));
User deSerializer = serializer.deSerializer(bytes, User.class);
System.out.println(deSerializer);
}
}
4. 高阶认识
4.1 serialVersionUID 的作用
-
Java的序列化机制是通过判断类的 serialVersionUID 来验证版本一致性的。
-
在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体的serialVersionUID进行比较,如果相同就认为时一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常,即是 InvalidCastException。
-
如果没有为指定的 class 配置 serialVersionUID,那么 java 编译器会自动给这个 class 进行一个摘要算法,类似于指纹算法,只要这个文件有任何改动,得到的 UID 就会截然不同的,可以保证在这么多类中,这个编号是唯一的
4.2 静态变量序列化
序列化保存的是对象的状态,静态变量属于类的状态,因此序列化并不保存静态变量。
4.3 父类的序列化
-
当一个父类没有实现序列化时,子类继承该父类并且实现了序列化。在反序列化该子类后,是没办法获取到父类的属性的。
-
当一个父类实现序列化,子类自动实现序列化,不需要再显示实现Serializable 接口
-
当一个对象的实例变量引用了其他对象,序列化该对象时也会把引用对象进行序列化,但是前提是该引用对象必须实现序列化接口
4.4 Transient
-
Transient 关键字的作用是控制变量的序列化,在变量声明前加上该关键字,可以阻止该变量被序列化到文件中
-
在被反序列化后,transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null
5. 序列化实现深拷贝
-
浅克隆:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象
-
深克隆:
-
被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的值。
-
那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的哪些被引用的对象。
-
深拷贝把要复制的对象所引用的对象都复制了一遍。
package com.zwz.serializer;
import java.io.*;
/**
* @description: 实现深克隆效果
* 把对象序列化输出到一个流中,然后对象序列化流中读取出来,这个对象就不是原来的对象了。
* @date : 2020/1/8 15:23
* @author: zwz
*/
public class Person implements Cloneable, Serializable {
private static final long serialVersionUID = 5532843697249498959L;
private String name;
private Email email;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Email getEmail() {
return email;
}
public void setEmail(Email email) {
this.email = email;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", email=" + email.getContent() +
'}';
}
@Override
protected Person clone() throws CloneNotSupportedException {
return (Person) super.clone();
}
public Person deepClone() throws IOException, ClassNotFoundException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(this);
byte[] data = byteArrayOutputStream.toByteArray();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data);
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
Object object = objectInputStream.readObject();
return (Person) object;
}
public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
Email email = new Email();
email.setContent("8:00");
Person person = new Person();
person.setName("mic");
person.setEmail(email);
Person person1 = person.deepClone();
person1.setName("mak");
person1.getEmail().setContent("9:00");
System.out.println(person.getName() + "->" + person.getEmail().getContent());
System.out.println(person1.getName() + "->" + person1.getEmail().getContent());
System.out.println("-------------");
Person person2 = person.clone();
person2.setName("mac");
person2.getEmail().setContent("10:00");
System.out.println(person.getName() + "->" + person.getEmail().getContent());
System.out.println(person1.getName() + "->" + person1.getEmail().getContent());
System.out.println(person2.getName() + "->" + person2.getEmail().getContent());
}
/**
* @description:
* @date : 2020/1/8 15:21
* @author: zwz
*/
public static class Email implements Serializable {
private static final long serialVersionUID = -2800552551799395733L;
public Email(String content) {
this.content = content;
}
private String content;
public Email() {
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
}
6. 常见的序列化技术
6.1 使用 JAVA 进行序列化有他的优点,也有他的缺点
-
优点:JAVA 语言本身提供,使用比较方便和简单
-
缺点:不支持跨语言处理、 性能相对不是很好,序列化以后产生的数据相对较大
6.2 XML 序列化框架
-
XML 序列化的好处在于可读性好,方便阅读和调试。
-
但是序列化以后的字节码文件比较大,而且效率不高。
-
适用于对性能不高,而且 QPS 较低的企业级内部系统之间的数据交换的场景。
-
同时 XML 又具有语言无关性,所以还可以用于异构系统之间的数据交换和协议。
-
Webservice采用 XML 格式对数据进行序列化的
package com.gp.lock.serizlizer;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
/**
* @description:
* @date : 2020/1/8 15:54
* @author: zwz
*/
public class XmlSerializer implements ISerializer {
XStream xStream = new XStream(new DomDriver());
public <T> byte[] serializer(T obj) {
return xStream.toXML(obj).getBytes();
}
public <T> T deSerializer(byte[] data, Class<T> clazz) {
return (T) xStream.fromXML(new String(data));
}
}
6.3 JSON 序列化
-
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,相对于 XML 来说,JSON 的字节流更小,而且可读性也非常好。
-
现在 JSON数据格式在企业运用是最普遍的。JSON 序列化常用的开源工具有很多
- Jackson (https://github.com/FasterXML/jackson)
- 阿里开源的 FastJson (https://github.com/alibaba/fastjon)
- Google 的 GSON (https://github.com/google/gson)
-
这几种 json 序列化工具中,Jackson 与 fastjson 要比 GSON 的性能要好,但是 Jackson、GSON 的稳定性要比 Fastjson 好。
-
而 fastjson 的优势在于提供的 api 非常容易使用
package com.gp.lock.serizlizer;
import com.alibaba.fastjson.JSON;
/**
* @description:
* @date : 2020/1/8 16:12
* @author: zwz
*/
public class FastJsonSerializer implements ISerializer {
public <T> byte[] serializer(T obj) {
return JSON.toJSONString(obj).getBytes();
}
public <T> T deSerializer(byte[] data, Class<T> clazz) {
return JSON.parseObject(new String(data), clazz);
}
}
6.4 Hessian 序列化框架
-
Hessian 是一个支持跨语言传输的二进制序列化协议,相对于 Java 默认的序列化机制来说,Hessian 具有更好的性能和易用性,而且支持多种不同的语言
-
Dubbo 采用的就是 Hessian 序列化来实现,只不过 Dubbo 对Hessian 进行了重构,性能更高
7. Protobuf(Protocol Buffer) 序列化框架
7.1 简介
-
Protobuf 是 Google 的一种数据交换格式,它独立于语言、独立于平台。
-
Google 提供了多种语言来实现,比如 Java、C、Go、Python,每一种实现都包含了相应语言的编译器和库文件。
-
Protobuf 使用比较广泛,主要是空间开销小和性能比较好,非常适合用于公司内部对性能要求高的 RPC 调用。
-
由于解析性能比较高,序列化以后数据量相对较少,所以也可以应用在对象的持久化场景中
-
但是要使用 Protobuf 会相对来说麻烦些,因为他有自己的语法,有自己的编译器
7.2 使用实例
-
到官网下载protobuf的相应版本,我这里下载的是windows下的3.1.0版protoc-3.1.0-win32.zip
-
将下载好的zip解压,能看到bin目录下有一个protoc.exe的文件,等下需要用它来编译文件,我们直接在bin目录下创建一个简单的person.proto的描述文件
syntax = "proto3";
option java_package = "com.gp.lock.serizlizer.protobuf";
option java_outer_classname = "PersonFactory";
message Person{
int32 id = 1;
string name = 2;
int32 age = 3;
Addr addr = 4;
}
message Addr{
string contry = 1;
string city = 2;
}
-
使用protoc编译上述.proto文件,生成Java类,使用如下命令完成该操作:protoc --java_out=./ ./person.proto
-
将PersonFactory.java文件引入到我们的项目中,并引入对应版本的protobuf的依赖包
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: person.proto
package com.gp.lock.serizlizer.protobuf;
public final class PersonFactory {
private PersonFactory() {
}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistryLite registry) {
}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistry registry) {
registerAllExtensions(
(com.google.protobuf.ExtensionRegistryLite) registry);
}
public interface PersonOrBuilder extends
// @@protoc_insertion_point(interface_extends:Person)
com.google.protobuf.MessageOrBuilder {
/**
* <code>optional int32 id = 1;</code>
*/
int getId();
/**
* <code>optional string name = 2;</code>
*/
String getName();
/**
* <code>optional string name = 2;</code>
*/
com.google.protobuf.ByteString
getNameBytes();
/**
* <code>optional int32 age = 3;</code>
*/
int getAge();
/**
* <code>optional .Addr addr = 4;</code>
*/
boolean hasAddr();
/**
* <code>optional .Addr addr = 4;</code>
*/
Addr getAddr();
/**
* <code>optional .Addr addr = 4;</code>
*/
AddrOrBuilder getAddrOrBuilder();
}
/**
* Protobuf type {@code Person}
*/
public static final class Person extends
com.google.protobuf.GeneratedMessageV3 implements
// @@protoc_insertion_point(message_implements:Person)
PersonOrBuilder {
// Use Person.newBuilder() to construct.
private Person(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
super(builder);
}
private Person() {
id_ = 0;
name_ = "";
age_ = 0;
}
@Override
public final com.google.protobuf.UnknownFieldSet
getUnknownFields() {
return com.google.protobuf.UnknownFieldSet.getDefaultInstance();
}
private Person(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
this();
int mutable_bitField0_ = 0;
try {
boolean done = false;
while (!done) {
int tag = input.readTag();
switch (tag) {
case 0:
done = true;
break;
default: {
if (!input.skipField(tag)) {
done = true;
}
break;
}
case 8: {
id_ = input.readInt32();
break;
}
case 18: {
String s = input.readStringRequireUtf8();
name_ = s;
break;
}
case 24: {
age_ = input.readInt32();
break;
}
case 34: {
Addr.Builder subBuilder = null;
if (addr_ != null) {
subBuilder = addr_.toBuilder();
}
addr_ = input.readMessage(Addr.parser(), extensionRegistry);
if (subBuilder != null) {
subBuilder.mergeFrom(addr_);
addr_ = subBuilder.buildPartial();
}
break;
}
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(this);
} catch (java.io.IOException e) {
throw new com.google.protobuf.InvalidProtocolBufferException(
e).setUnfinishedMessage(this);
} finally {
makeExtensionsImmutable();
}
}
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return PersonFactory.internal_static_Person_descriptor;
}
protected FieldAccessorTable
internalGetFieldAccessorTable() {
return PersonFactory.internal_static_Person_fieldAccessorTable
.ensureFieldAccessorsInitialized(
Person.class, Builder.class);
}
public static final int ID_FIELD_NUMBER = 1;
private int id_;
/**
* <code>optional int32 id = 1;</code>
*/
public int getId() {
return id_;
}
public static final int NAME_FIELD_NUMBER = 2;
private volatile Object name_;
/**
* <code>optional string name = 2;</code>
*/
public String getName() {
Object ref = name_;
if (ref instanceof String) {
return (String) ref;
} else {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
String s = bs.toStringUtf8();
name_ = s;
return s;
}
}
/**
* <code>optional string name = 2;</code>
*/
public com.google.protobuf.ByteString
getNameBytes() {
Object ref = name_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(String) ref);
name_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
public static final int AGE_FIELD_NUMBER = 3;
private int age_;
/**
* <code>optional int32 age = 3;</code>
*/
public int getAge() {
return age_;
}
public static final int ADDR_FIELD_NUMBER = 4;
private Addr addr_;
/**
* <code>optional .Addr addr = 4;</code>
*/
public boolean hasAddr() {
return addr_ != null;
}
/**
* <code>optional .Addr addr = 4;</code>
*/
public Addr getAddr() {
return addr_ == null ? Addr.getDefaultInstance() : addr_;
}
/**
* <code>optional .Addr addr = 4;</code>
*/
public AddrOrBuilder getAddrOrBuilder() {
return getAddr();
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
byte isInitialized = memoizedIsInitialized;
if (isInitialized == 1) return true;
if (isInitialized == 0) return false;
memoizedIsInitialized = 1;
return true;
}
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
if (id_ != 0) {
output.writeInt32(1, id_);
}
if (!getNameBytes().isEmpty()) {
com.google.protobuf.GeneratedMessageV3.writeString(output, 2, name_);
}
if (age_ != 0) {
output.writeInt32(3, age_);
}
if (addr_ != null) {
output.writeMessage(4, getAddr());
}
}
public int getSerializedSize() {
int size = memoizedSize;
if (size != -1) return size;
size = 0;
if (id_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(1, id_);
}
if (!getNameBytes().isEmpty()) {
size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, name_);
}
if (age_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(3, age_);
}
if (addr_ != null) {
size += com.google.protobuf.CodedOutputStream
.computeMessageSize(4, getAddr());
}
memoizedSize = size;
return size;
}
private static final long serialVersionUID = 0L;
@Override
public boolean equals(final Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof Person)) {
return super.equals(obj);
}
Person other = (Person) obj;
boolean result = true;
result = result && (getId()
== other.getId());
result = result && getName()
.equals(other.getName());
result = result && (getAge()
== other.getAge());
result = result && (hasAddr() == other.hasAddr());
if (hasAddr()) {
result = result && getAddr()
.equals(other.getAddr());
}
return result;
}
@Override
public int hashCode() {
if (memoizedHashCode != 0) {
return memoizedHashCode;
}
int hash = 41;
hash = (19 * hash) + getDescriptorForType().hashCode();
hash = (37 * hash) + ID_FIELD_NUMBER;
hash = (53 * hash) + getId();
hash = (37 * hash) + NAME_FIELD_NUMBER;
hash = (53 * hash) + getName().hashCode();
hash = (37 * hash) + AGE_FIELD_NUMBER;
hash = (53 * hash) + getAge();
if (hasAddr()) {
hash = (37 * hash) + ADDR_FIELD_NUMBER;
hash = (53 * hash) + getAddr().hashCode();
}
hash = (29 * hash) + unknownFields.hashCode();
memoizedHashCode = hash;
return hash;
}
public static Person parseFrom(
com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static Person parseFrom(
com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static Person parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static Person parseFrom(
byte[] data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static Person parseFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input);
}
public static Person parseFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input, extensionRegistry);
}
public static Person parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseDelimitedWithIOException(PARSER, input);
}
public static Person parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseDelimitedWithIOException(PARSER, input, extensionRegistry);
}
public static Person parseFrom(
com.google.protobuf.CodedInputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input);
}
public static Person parseFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input, extensionRegistry);
}
public Builder newBuilderForType() {
return newBuilder();
}
public static Builder newBuilder() {
return DEFAULT_INSTANCE.toBuilder();
}
public static Builder newBuilder(Person prototype) {
return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
}
public Builder toBuilder() {
return this == DEFAULT_INSTANCE
? new Builder() : new Builder().mergeFrom(this);
}
@Override
protected Builder newBuilderForType(
BuilderParent parent) {
Builder builder = new Builder(parent);
return builder;
}
/**
* Protobuf type {@code Person}
*/
public static final class Builder extends
com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
// @@protoc_insertion_point(builder_implements:Person)
PersonOrBuilder {
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return PersonFactory.internal_static_Person_descriptor;
}
protected FieldAccessorTable
internalGetFieldAccessorTable() {
return PersonFactory.internal_static_Person_fieldAccessorTable
.ensureFieldAccessorsInitialized(
Person.class, Builder.class);
}
// Construct using com.gp.lock.serizlizer.protobuf.PersonFactory.Person.newBuilder()
private Builder() {
maybeForceBuilderInitialization();
}
private Builder(
BuilderParent parent) {
super(parent);
maybeForceBuilderInitialization();
}
private void maybeForceBuilderInitialization() {
if (com.google.protobuf.GeneratedMessageV3
.alwaysUseFieldBuilders) {
}
}
public Builder clear() {
super.clear();
id_ = 0;
name_ = "";
age_ = 0;
if (addrBuilder_ == null) {
addr_ = null;
} else {
addr_ = null;
addrBuilder_ = null;
}
return this;
}
public com.google.protobuf.Descriptors.Descriptor
getDescriptorForType() {
return PersonFactory.internal_static_Person_descriptor;
}
public Person getDefaultInstanceForType() {
return Person.getDefaultInstance();
}
public Person build() {
Person result = buildPartial();
if (!result.isInitialized()) {
throw newUninitializedMessageException(result);
}
return result;
}
public Person buildPartial() {
Person result = new Person(this);
result.id_ = id_;
result.name_ = name_;
result.age_ = age_;
if (addrBuilder_ == null) {
result.addr_ = addr_;
} else {
result.addr_ = addrBuilder_.build();
}
onBuilt();
return result;
}
public Builder clone() {
return (Builder) super.clone();
}
public Builder setField(
com.google.protobuf.Descriptors.FieldDescriptor field,
Object value) {
return (Builder) super.setField(field, value);
}
public Builder clearField(
com.google.protobuf.Descriptors.FieldDescriptor field) {
return (Builder) super.clearField(field);
}
public Builder clearOneof(
com.google.protobuf.Descriptors.OneofDescriptor oneof) {
return (Builder) super.clearOneof(oneof);
}
public Builder setRepeatedField(
com.google.protobuf.Descriptors.FieldDescriptor field,
int index, Object value) {
return (Builder) super.setRepeatedField(field, index, value);
}
public Builder addRepeatedField(
com.google.protobuf.Descriptors.FieldDescriptor field,
Object value) {
return (Builder) super.addRepeatedField(field, value);
}
public Builder mergeFrom(com.google.protobuf.Message other) {
if (other instanceof Person) {
return mergeFrom((Person) other);
} else {
super.mergeFrom(other);
return this;
}
}
public Builder mergeFrom(Person other) {
if (other == Person.getDefaultInstance()) return this;
if (other.getId() != 0) {
setId(other.getId());
}
if (!other.getName().isEmpty()) {
name_ = other.name_;
onChanged();
}
if (other.getAge() != 0) {
setAge(other.getAge());
}
if (other.hasAddr()) {
mergeAddr(other.getAddr());
}
onChanged();
return this;
}
public final boolean isInitialized() {
return true;
}
public Builder mergeFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
Person parsedMessage = null;
try {
parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
parsedMessage = (Person) e.getUnfinishedMessage();
throw e.unwrapIOException();
} finally {
if (parsedMessage != null) {
mergeFrom(parsedMessage);
}
}
return this;
}
private int id_;
/**
* <code>optional int32 id = 1;</code>
*/
public int getId() {
return id_;
}
/**
* <code>optional int32 id = 1;</code>
*/
public Builder setId(int value) {
id_ = value;
onChanged();
return this;
}
/**
* <code>optional int32 id = 1;</code>
*/
public Builder clearId() {
id_ = 0;
onChanged();
return this;
}
private Object name_ = "";
/**
* <code>optional string name = 2;</code>
*/
public String getName() {
Object ref = name_;
if (!(ref instanceof String)) {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
String s = bs.toStringUtf8();
name_ = s;
return s;
} else {
return (String) ref;
}
}
/**
* <code>optional string name = 2;</code>
*/
public com.google.protobuf.ByteString
getNameBytes() {
Object ref = name_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(String) ref);
name_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
/**
* <code>optional string name = 2;</code>
*/
public Builder setName(
String value) {
if (value == null) {
throw new NullPointerException();
}
name_ = value;
onChanged();
return this;
}
/**
* <code>optional string name = 2;</code>
*/
public Builder clearName() {
name_ = getDefaultInstance().getName();
onChanged();
return this;
}
/**
* <code>optional string name = 2;</code>
*/
public Builder setNameBytes(
com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
checkByteStringIsUtf8(value);
name_ = value;
onChanged();
return this;
}
private int age_;
/**
* <code>optional int32 age = 3;</code>
*/
public int getAge() {
return age_;
}
/**
* <code>optional int32 age = 3;</code>
*/
public Builder setAge(int value) {
age_ = value;
onChanged();
return this;
}
/**
* <code>optional int32 age = 3;</code>
*/
public Builder clearAge() {
age_ = 0;
onChanged();
return this;
}
private Addr addr_ = null;
private com.google.protobuf.SingleFieldBuilderV3<
Addr, Addr.Builder, AddrOrBuilder> addrBuilder_;
/**
* <code>optional .Addr addr = 4;</code>
*/
public boolean hasAddr() {
return addrBuilder_ != null || addr_ != null;
}
/**
* <code>optional .Addr addr = 4;</code>
*/
public Addr getAddr() {
if (addrBuilder_ == null) {
return addr_ == null ? Addr.getDefaultInstance() : addr_;
} else {
return addrBuilder_.getMessage();
}
}
/**
* <code>optional .Addr addr = 4;</code>
*/
public Builder setAddr(Addr value) {
if (addrBuilder_ == null) {
if (value == null) {
throw new NullPointerException();
}
addr_ = value;
onChanged();
} else {
addrBuilder_.setMessage(value);
}
return this;
}
/**
* <code>optional .Addr addr = 4;</code>
*/
public Builder setAddr(
Addr.Builder builderForValue) {
if (addrBuilder_ == null) {
addr_ = builderForValue.build();
onChanged();
} else {
addrBuilder_.setMessage(builderForValue.build());
}
return this;
}
/**
* <code>optional .Addr addr = 4;</code>
*/
public Builder mergeAddr(Addr value) {
if (addrBuilder_ == null) {
if (addr_ != null) {
addr_ =
Addr.newBuilder(addr_).mergeFrom(value).buildPartial();
} else {
addr_ = value;
}
onChanged();
} else {
addrBuilder_.mergeFrom(value);
}
return this;
}
/**
* <code>optional .Addr addr = 4;</code>
*/
public Builder clearAddr() {
if (addrBuilder_ == null) {
addr_ = null;
onChanged();
} else {
addr_ = null;
addrBuilder_ = null;
}
return this;
}
/**
* <code>optional .Addr addr = 4;</code>
*/
public Addr.Builder getAddrBuilder() {
onChanged();
return getAddrFieldBuilder().getBuilder();
}
/**
* <code>optional .Addr addr = 4;</code>
*/
public AddrOrBuilder getAddrOrBuilder() {
if (addrBuilder_ != null) {
return addrBuilder_.getMessageOrBuilder();
} else {
return addr_ == null ?
Addr.getDefaultInstance() : addr_;
}
}
/**
* <code>optional .Addr addr = 4;</code>
*/
private com.google.protobuf.SingleFieldBuilderV3<
Addr, Addr.Builder, AddrOrBuilder>
getAddrFieldBuilder() {
if (addrBuilder_ == null) {
addrBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
Addr, Addr.Builder, AddrOrBuilder>(
getAddr(),
getParentForChildren(),
isClean());
addr_ = null;
}
return addrBuilder_;
}
public final Builder setUnknownFields(
final com.google.protobuf.UnknownFieldSet unknownFields) {
return this;
}
public final Builder mergeUnknownFields(
final com.google.protobuf.UnknownFieldSet unknownFields) {
return this;
}
// @@protoc_insertion_point(builder_scope:Person)
}
// @@protoc_insertion_point(class_scope:Person)
private static final Person DEFAULT_INSTANCE;
static {
DEFAULT_INSTANCE = new Person();
}
public static Person getDefaultInstance() {
return DEFAULT_INSTANCE;
}
private static final com.google.protobuf.Parser<Person>
PARSER = new com.google.protobuf.AbstractParser<Person>() {
public Person parsePartialFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return new Person(input, extensionRegistry);
}
};
public static com.google.protobuf.Parser<Person> parser() {
return PARSER;
}
@Override
public com.google.protobuf.Parser<Person> getParserForType() {
return PARSER;
}
public Person getDefaultInstanceForType() {
return DEFAULT_INSTANCE;
}
}
public interface AddrOrBuilder extends
// @@protoc_insertion_point(interface_extends:Addr)
com.google.protobuf.MessageOrBuilder {
/**
* <code>optional string contry = 1;</code>
*/
String getContry();
/**
* <code>optional string contry = 1;</code>
*/
com.google.protobuf.ByteString
getContryBytes();
/**
* <code>optional string city = 2;</code>
*/
String getCity();
/**
* <code>optional string city = 2;</code>
*/
com.google.protobuf.ByteString
getCityBytes();
}
/**
* Protobuf type {@code Addr}
*/
public static final class Addr extends
com.google.protobuf.GeneratedMessageV3 implements
// @@protoc_insertion_point(message_implements:Addr)
AddrOrBuilder {
// Use Addr.newBuilder() to construct.
private Addr(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
super(builder);
}
private Addr() {
contry_ = "";
city_ = "";
}
@Override
public final com.google.protobuf.UnknownFieldSet
getUnknownFields() {
return com.google.protobuf.UnknownFieldSet.getDefaultInstance();
}
private Addr(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
this();
int mutable_bitField0_ = 0;
try {
boolean done = false;
while (!done) {
int tag = input.readTag();
switch (tag) {
case 0:
done = true;
break;
default: {
if (!input.skipField(tag)) {
done = true;
}
break;
}
case 10: {
String s = input.readStringRequireUtf8();
contry_ = s;
break;
}
case 18: {
String s = input.readStringRequireUtf8();
city_ = s;
break;
}
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(this);
} catch (java.io.IOException e) {
throw new com.google.protobuf.InvalidProtocolBufferException(
e).setUnfinishedMessage(this);
} finally {
makeExtensionsImmutable();
}
}
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return PersonFactory.internal_static_Addr_descriptor;
}
protected FieldAccessorTable
internalGetFieldAccessorTable() {
return PersonFactory.internal_static_Addr_fieldAccessorTable
.ensureFieldAccessorsInitialized(
Addr.class, Builder.class);
}
public static final int CONTRY_FIELD_NUMBER = 1;
private volatile Object contry_;
/**
* <code>optional string contry = 1;</code>
*/
public String getContry() {
Object ref = contry_;
if (ref instanceof String) {
return (String) ref;
} else {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
String s = bs.toStringUtf8();
contry_ = s;
return s;
}
}
/**
* <code>optional string contry = 1;</code>
*/
public com.google.protobuf.ByteString
getContryBytes() {
Object ref = contry_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(String) ref);
contry_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
public static final int CITY_FIELD_NUMBER = 2;
private volatile Object city_;
/**
* <code>optional string city = 2;</code>
*/
public String getCity() {
Object ref = city_;
if (ref instanceof String) {
return (String) ref;
} else {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
String s = bs.toStringUtf8();
city_ = s;
return s;
}
}
/**
* <code>optional string city = 2;</code>
*/
public com.google.protobuf.ByteString
getCityBytes() {
Object ref = city_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(String) ref);
city_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
byte isInitialized = memoizedIsInitialized;
if (isInitialized == 1) return true;
if (isInitialized == 0) return false;
memoizedIsInitialized = 1;
return true;
}
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
if (!getContryBytes().isEmpty()) {
com.google.protobuf.GeneratedMessageV3.writeString(output, 1, contry_);
}
if (!getCityBytes().isEmpty()) {
com.google.protobuf.GeneratedMessageV3.writeString(output, 2, city_);
}
}
public int getSerializedSize() {
int size = memoizedSize;
if (size != -1) return size;
size = 0;
if (!getContryBytes().isEmpty()) {
size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, contry_);
}
if (!getCityBytes().isEmpty()) {
size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, city_);
}
memoizedSize = size;
return size;
}
private static final long serialVersionUID = 0L;
@Override
public boolean equals(final Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof Addr)) {
return super.equals(obj);
}
Addr other = (Addr) obj;
boolean result = true;
result = result && getContry()
.equals(other.getContry());
result = result && getCity()
.equals(other.getCity());
return result;
}
@Override
public int hashCode() {
if (memoizedHashCode != 0) {
return memoizedHashCode;
}
int hash = 41;
hash = (19 * hash) + getDescriptorForType().hashCode();
hash = (37 * hash) + CONTRY_FIELD_NUMBER;
hash = (53 * hash) + getContry().hashCode();
hash = (37 * hash) + CITY_FIELD_NUMBER;
hash = (53 * hash) + getCity().hashCode();
hash = (29 * hash) + unknownFields.hashCode();
memoizedHashCode = hash;
return hash;
}
public static Addr parseFrom(
com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static Addr parseFrom(
com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static Addr parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static Addr parseFrom(
byte[] data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static Addr parseFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input);
}
public static Addr parseFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input, extensionRegistry);
}
public static Addr parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseDelimitedWithIOException(PARSER, input);
}
public static Addr parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseDelimitedWithIOException(PARSER, input, extensionRegistry);
}
public static Addr parseFrom(
com.google.protobuf.CodedInputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input);
}
public static Addr parseFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input, extensionRegistry);
}
public Builder newBuilderForType() {
return newBuilder();
}
public static Builder newBuilder() {
return DEFAULT_INSTANCE.toBuilder();
}
public static Builder newBuilder(Addr prototype) {
return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
}
public Builder toBuilder() {
return this == DEFAULT_INSTANCE
? new Builder() : new Builder().mergeFrom(this);
}
@Override
protected Builder newBuilderForType(
BuilderParent parent) {
Builder builder = new Builder(parent);
return builder;
}
/**
* Protobuf type {@code Addr}
*/
public static final class Builder extends
com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
// @@protoc_insertion_point(builder_implements:Addr)
AddrOrBuilder {
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return PersonFactory.internal_static_Addr_descriptor;
}
protected FieldAccessorTable
internalGetFieldAccessorTable() {
return PersonFactory.internal_static_Addr_fieldAccessorTable
.ensureFieldAccessorsInitialized(
Addr.class, Builder.class);
}
// Construct using com.gp.lock.serizlizer.protobuf.PersonFactory.Addr.newBuilder()
private Builder() {
maybeForceBuilderInitialization();
}
private Builder(
BuilderParent parent) {
super(parent);
maybeForceBuilderInitialization();
}
private void maybeForceBuilderInitialization() {
if (com.google.protobuf.GeneratedMessageV3
.alwaysUseFieldBuilders) {
}
}
public Builder clear() {
super.clear();
contry_ = "";
city_ = "";
return this;
}
public com.google.protobuf.Descriptors.Descriptor
getDescriptorForType() {
return PersonFactory.internal_static_Addr_descriptor;
}
public Addr getDefaultInstanceForType() {
return Addr.getDefaultInstance();
}
public Addr build() {
Addr result = buildPartial();
if (!result.isInitialized()) {
throw newUninitializedMessageException(result);
}
return result;
}
public Addr buildPartial() {
Addr result = new Addr(this);
result.contry_ = contry_;
result.city_ = city_;
onBuilt();
return result;
}
public Builder clone() {
return (Builder) super.clone();
}
public Builder setField(
com.google.protobuf.Descriptors.FieldDescriptor field,
Object value) {
return (Builder) super.setField(field, value);
}
public Builder clearField(
com.google.protobuf.Descriptors.FieldDescriptor field) {
return (Builder) super.clearField(field);
}
public Builder clearOneof(
com.google.protobuf.Descriptors.OneofDescriptor oneof) {
return (Builder) super.clearOneof(oneof);
}
public Builder setRepeatedField(
com.google.protobuf.Descriptors.FieldDescriptor field,
int index, Object value) {
return (Builder) super.setRepeatedField(field, index, value);
}
public Builder addRepeatedField(
com.google.protobuf.Descriptors.FieldDescriptor field,
Object value) {
return (Builder) super.addRepeatedField(field, value);
}
public Builder mergeFrom(com.google.protobuf.Message other) {
if (other instanceof Addr) {
return mergeFrom((Addr) other);
} else {
super.mergeFrom(other);
return this;
}
}
public Builder mergeFrom(Addr other) {
if (other == Addr.getDefaultInstance()) return this;
if (!other.getContry().isEmpty()) {
contry_ = other.contry_;
onChanged();
}
if (!other.getCity().isEmpty()) {
city_ = other.city_;
onChanged();
}
onChanged();
return this;
}
public final boolean isInitialized() {
return true;
}
public Builder mergeFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
Addr parsedMessage = null;
try {
parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
parsedMessage = (Addr) e.getUnfinishedMessage();
throw e.unwrapIOException();
} finally {
if (parsedMessage != null) {
mergeFrom(parsedMessage);
}
}
return this;
}
private Object contry_ = "";
/**
* <code>optional string contry = 1;</code>
*/
public String getContry() {
Object ref = contry_;
if (!(ref instanceof String)) {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
String s = bs.toStringUtf8();
contry_ = s;
return s;
} else {
return (String) ref;
}
}
/**
* <code>optional string contry = 1;</code>
*/
public com.google.protobuf.ByteString
getContryBytes() {
Object ref = contry_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(String) ref);
contry_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
/**
* <code>optional string contry = 1;</code>
*/
public Builder setContry(
String value) {
if (value == null) {
throw new NullPointerException();
}
contry_ = value;
onChanged();
return this;
}
/**
* <code>optional string contry = 1;</code>
*/
public Builder clearContry() {
contry_ = getDefaultInstance().getContry();
onChanged();
return this;
}
/**
* <code>optional string contry = 1;</code>
*/
public Builder setContryBytes(
com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
checkByteStringIsUtf8(value);
contry_ = value;
onChanged();
return this;
}
private Object city_ = "";
/**
* <code>optional string city = 2;</code>
*/
public String getCity() {
Object ref = city_;
if (!(ref instanceof String)) {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
String s = bs.toStringUtf8();
city_ = s;
return s;
} else {
return (String) ref;
}
}
/**
* <code>optional string city = 2;</code>
*/
public com.google.protobuf.ByteString
getCityBytes() {
Object ref = city_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(String) ref);
city_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
/**
* <code>optional string city = 2;</code>
*/
public Builder setCity(
String value) {
if (value == null) {
throw new NullPointerException();
}
city_ = value;
onChanged();
return this;
}
/**
* <code>optional string city = 2;</code>
*/
public Builder clearCity() {
city_ = getDefaultInstance().getCity();
onChanged();
return this;
}
/**
* <code>optional string city = 2;</code>
*/
public Builder setCityBytes(
com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
checkByteStringIsUtf8(value);
city_ = value;
onChanged();
return this;
}
public final Builder setUnknownFields(
final com.google.protobuf.UnknownFieldSet unknownFields) {
return this;
}
public final Builder mergeUnknownFields(
final com.google.protobuf.UnknownFieldSet unknownFields) {
return this;
}
// @@protoc_insertion_point(builder_scope:Addr)
}
// @@protoc_insertion_point(class_scope:Addr)
private static final Addr DEFAULT_INSTANCE;
static {
DEFAULT_INSTANCE = new Addr();
}
public static Addr getDefaultInstance() {
return DEFAULT_INSTANCE;
}
private static final com.google.protobuf.Parser<Addr>
PARSER = new com.google.protobuf.AbstractParser<Addr>() {
public Addr parsePartialFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return new Addr(input, extensionRegistry);
}
};
public static com.google.protobuf.Parser<Addr> parser() {
return PARSER;
}
@Override
public com.google.protobuf.Parser<Addr> getParserForType() {
return PARSER;
}
public Addr getDefaultInstanceForType() {
return DEFAULT_INSTANCE;
}
}
private static final com.google.protobuf.Descriptors.Descriptor
internal_static_Person_descriptor;
private static final
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
internal_static_Person_fieldAccessorTable;
private static final com.google.protobuf.Descriptors.Descriptor
internal_static_Addr_descriptor;
private static final
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
internal_static_Addr_fieldAccessorTable;
public static com.google.protobuf.Descriptors.FileDescriptor
getDescriptor() {
return descriptor;
}
private static com.google.protobuf.Descriptors.FileDescriptor
descriptor;
static {
String[] descriptorData = {
"\n\014person.proto\"D\n\006Person\022\n\n\002id\030\001 \001(\005\022\014\n\004" +
"name\030\002 \001(\t\022\013\n\003age\030\003 \001(\005\022\023\n\004addr\030\004 \001(\0132\005." +
"Addr\"$\n\004Addr\022\016\n\006contry\030\001 \001(\t\022\014\n\004city\030\002 \001" +
"(\tB0\n\037com.gp.lock.serizlizer.protobufB\rP" +
"ersonFactoryb\006proto3"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
public com.google.protobuf.ExtensionRegistry assignDescriptors(
com.google.protobuf.Descriptors.FileDescriptor root) {
descriptor = root;
return null;
}
};
com.google.protobuf.Descriptors.FileDescriptor
.internalBuildGeneratedFileFrom(descriptorData,
new com.google.protobuf.Descriptors.FileDescriptor[]{
}, assigner);
internal_static_Person_descriptor =
getDescriptor().getMessageTypes().get(0);
internal_static_Person_fieldAccessorTable = new
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
internal_static_Person_descriptor,
new String[]{"Id", "Name", "Age", "Addr",});
internal_static_Addr_descriptor =
getDescriptor().getMessageTypes().get(1);
internal_static_Addr_fieldAccessorTable = new
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
internal_static_Addr_descriptor,
new String[]{"Contry", "City",});
}
// @@protoc_insertion_point(outer_class_scope)
}
package com.gp.lock.serizlizer.protobuf;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
ServerSocket serverSock = new ServerSocket(3030);
while (true) {
Socket sock = serverSock.accept();
byte[] msg = new byte[256];
sock.getInputStream().read(msg);
int msgBodyLen = msg[0];
System.out.println("msg body len:" + msgBodyLen);
byte[] msgbody = new byte[msgBodyLen];
System.arraycopy(msg, 1, msgbody, 0, msgBodyLen);
System.out.println("msgbody = " + new String(msgbody));
PersonFactory.Person person = PersonFactory.Person.parseFrom(msgbody);
System.out.println("Receive:");
System.out.println(person);
}
}
}
package com.gp.lock.serizlizer.protobuf;
import com.gp.lock.serizlizer.protobuf.PersonFactory.Addr;
import com.gp.lock.serizlizer.protobuf.PersonFactory.Person;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("127.0.0.1", 3030);
Person.Builder person = Person.newBuilder();
Addr.Builder addr = Addr.newBuilder();
addr.setContry("china").setCity("shenzhen");
person.setId(1).setAge(12).setName("ccf");
person.setAddr(addr);
byte[] messageBody = person.build().toByteArray();
System.out.println("messageBody = " + new String(messageBody));
int headerLen = 1;
byte[] message = new byte[headerLen + messageBody.length];
message[0] = (byte) messageBody.length;
System.arraycopy(messageBody, 0, message, 1, messageBody.length);
System.out.println("msg len:" + message.length);
socket.getOutputStream().write(message);
}
}
结果
"C:\Program Files\Java\jdk1.8.0_211\bin\java.exe" -Dvisualvm.id=443604366717400 "-javaagent:D:\DevelopTools\IDEA\IntelliJ IDEA 2019.2.2\lib\idea_rt.jar=12578:D:\DevelopTools\IDEA\IntelliJ IDEA 2019.2.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_211\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\rt.jar;E:\CODE\Architecture\serializer\target\classes;C:\Users\zwz\.m2\repository\com\thoughtworks\xstream\xstream\1.4.10\xstream-1.4.10.jar;C:\Users\zwz\.m2\repository\xmlpull\xmlpull\1.1.3.1\xmlpull-1.1.3.1.jar;C:\Users\zwz\.m2\repository\xpp3\xpp3_min\1.1.4c\xpp3_min-1.1.4c.jar;C:\Users\zwz\.m2\repository\com\alibaba\fastjson\1.2.31\fastjson-1.2.31.jar;C:\Users\zwz\.m2\repository\io\netty\netty-all\4.1.45.Final\netty-all-4.1.45.Final.jar;C:\Users\zwz\.m2\repository\junit\junit\4.12\junit-4.12.jar;C:\Users\zwz\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;C:\Users\zwz\.m2\repository\com\google\protobuf\protobuf-java\3.7.1\protobuf-java-3.7.1.jar" com.gp.lock.serizlizer.protobuf.Server
msg body len:28
msgbody =���ccf�"�
�chinashenzhen
Receive:
id: 1
name: "ccf"
age: 12
addr {
contry: "china"
city: "shenzhen"
}
7.3 protostuff
protostuff是一个基于protobuf实现的序列化方法,它较于protobuf最明显的好处是,在几乎不损耗性能的情况下做到了不用我们写.proto文件来实现序列化。
package com.gp.lock.serizlizer.protobuf;
import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
import java.util.ArrayList;
import java.util.List;
public class ProtostuffTest {
static RuntimeSchema<Po> poSchema = RuntimeSchema.createFrom(Po.class);
private static byte[] decode(Po po) {
return ProtostuffIOUtil.toByteArray(po, poSchema, LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE));
}
private static Po ecode(byte[] bytes) {
Po po = poSchema.newMessage();
ProtostuffIOUtil.mergeFrom(bytes, po, poSchema);
return po;
}
public static void main(String[] args) {
InnerPo innerPo = new InnerPo(1, "InnerPo1");
List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
Po po = new Po(1, "Fong", "备注", 24, new int[]{1, 2, 3, 4}, innerPo, list);
byte[] bytes = decode(po);
System.out.println(bytes.length);
Po newPo = ecode(bytes);
System.out.println(newPo);
}
}
运行结果
65
id:1
name:Fong
remark:备注
age:24
array:[1, 2, 3, 4]
innerPo:1-InnerPo1
more:[a, b]
模式
package com.asiainfo.dacp.brokerframe.protocol.rpc;
import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtobufIOUtil;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
import org.objenesis.Objenesis;
import org.objenesis.ObjenesisStd;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @description: Protostuff 序列化与反序列化工具
* @date : 2020/6/11 17:02
* @author: zwz
*/
public class SerializationUtil {
private static Map<Class<?>, Schema<?>> cacheSchema = new ConcurrentHashMap<>();
private static Objenesis objenesis = new ObjenesisStd(true);
public SerializationUtil() {
}
private static <T> Schema<T> getSchema(Class<T> cls) {
Schema<T> schema = (Schema<T>) cacheSchema.get(cls);
if (schema == null) {
schema = RuntimeSchema.createFrom(cls);
cacheSchema.put(cls, schema);
}
return schema;
}
public static <T> byte[] serialize(T obj) {
Class<T> cls = (Class<T>) obj.getClass();
LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
try {
Schema<T> schema = getSchema(cls);
//序列化:把 obj 按照 schema 模式 写入到 buffer
return ProtobufIOUtil.toByteArray(obj, schema, buffer);
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
} finally {
buffer.clear();
}
}
public static <T> T deserialized(byte[] data, Class<T> cls) {
try {
T message = objenesis.newInstance(cls);
Schema<T> schema = getSchema(cls);
//反序列化:将 data 按 schema 模式重建实例 message
ProtobufIOUtil.mergeFrom(data, message, schema);
return message;
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
}
7.4 Protocol Buffer 的性能好,主要体现在 序列化后的数据体积小 & 序列化速度快,最终使得传输效率高,其原因如下:
- 序列化速度快的原因:
-
编码 / 解码 方式简单(只需要简单的数学运算 = 位移等等)
-
采用 Protocol Buffer 自身的框架代码 和 编译器 共同完成
- 序列化后的数据量体积小(即数据压缩效果好)的原因:
-
采用了独特的编码方式,如 Varint、Zigzag 编码方式等等
-
采用 T - L - V 的数据存储方式:减少了分隔符的使用 & 数据存储得紧凑
8. 序列化技术选型
技术层面
-
序列化空间开销,也就是序列化产生的结果大小,这个影响到传输的性能
-
序列化过程中消耗的时长,序列化消耗时间过长影响到业务的响应时间
-
序列化协议是否支持跨平台,跨语言。因为现在的架构更加灵活,如果存在异构系统通信需求,那么这个是必须要考虑的
-
可扩展性/兼容性,在实际业务开发中,系统往往需要随着需求的快速迭代来实现快速更新,这就要求我们采用的序列化协议基于良好的可扩展性/兼容性,比如在现有的序列化数据结构中新增一个业务字段,不会影响到现有的服务
-
技术的流行程度,越流行的技术意味着使用的公司多,那么很多坑都已经淌过并且得到了解决,技术解决方案也相对成熟
-
学习难度和易用性
选型建议
-
对性能要求不高的场景,可以采用基于 XML 的 SOAP 协议
-
对性能和间接性有比较高要求的场景,那么 Hessian、Protobuf、Thrift、Avro 都可以。
-
基于前后端分离,或者独立的对外的 api 服务,选用 JSON 是比较好的,对于调试、可读性都很不错
-
Avro 设计理念偏于动态类型语言,那么这类的场景使用 Avro 是可以的