[轉載] Java序列化的幾種方式以及序列化的作用

參考鏈接: Java中帶有繼承的對象序列化

文章轉載自:? 本文著重講解一下Java序列化的相關內容。?

如果對Java序列化感興趣的同學可以研究一下。?

一.Java序列化的作用?

有的時候我們想要把一個Java對象變成字節流的形式傳出去,有的時候我們想要從一個字節流中恢復一個Java對象。例如,有的時候我們想要?

把一個Java對象寫入到硬盤或者傳輸到網路上面的其它計算機,這時我們就需要自己去通過java把相應的對象寫成轉換成字節流。對于這種通用?

的操作,我們為什么不使用統一的格式呢?沒錯,這里就出現了java的序列化的概念。在Java的OutputStream類下面的子類ObjectOutput-?

Stream類就有對應的WriteObject(Object object) 其中要求對應的object實現了java的序列化的接口。?

為了更好的理解java序列化的應用,我舉兩個自己在開發項目中遇到的例子:?

1)在使用tomcat開發JavaEE相關項目的時候,我們關閉tomcat后,相應的session中的對象就存儲在了硬盤上,如果我們想要在tomcat重啟的?

時候能夠從tomcat上面讀取對應session中的內容,那么保存在session中的內容就必須實現相關的序列化操作。?

2)如果我們使用的java對象要在分布式中使用或者在rmi遠程調用的網絡中使用的話,那么相關的對象必須實現java序列化接口。?

親愛的小伙伴,大概你已經了解了java序列化相關的作用,接下來們來看看如何實現java的序列化吧。~?

二.實現java對象的序列化和反序列化。?

? ? ? ?Java對象的序列化有兩種方式。

?

? ? ? ?a.是相應的對象實現了序列化接口Serializable,這個使用的比較多,對于序列化接口Serializable接口是一個空的接口,它的主要作用就是

?

? ? ? ? ?標識這個對象時可序列化的,jre對象在傳輸對象的時候會進行相關的封裝。這里就不做過多的介紹了。

?

? ? ? ? ?下面是一個實現序列化接口的Java序列化的例子:非常簡單

?

package com.shop.domain;

?

import java.util.Date;

?

?

public class Article implements java.io.Serializable {

? ? private static final long serialVersionUID = 1L;

? ? private Integer id;?

? ? private String title;? //文章標題

? ? private String content;? // 文章內容

? ? private String faceIcon;//表情圖標

? ? private Date postTime; //文章發表的時間

? ? private String ipAddr;? //用戶的ip

?

? ? private User author;? //回復的用戶

?

? ? public Integer getId() {

? ? ? ? return id;

? ? }

? ? public void setId(Integer id) {

? ? ? ? this.id = id;

? ? }

? ? public String getTitle() {

? ? ? ? return title;

? ? }

? ? public void setTitle(String title) {

? ? ? ? this.title = title;

? ? }

? ? public String getContent() {

? ? ? ? return content;

? ? }

? ? public void setContent(String content) {

? ? ? ? this.content = content;

? ? }

? ? public String getFaceIcon() {

? ? ? ? return faceIcon;

? ? }

? ? public void setFaceIcon(String faceIcon) {

? ? ? ? this.faceIcon = faceIcon;

? ? }

? ? public Date getPostTime() {

? ? ? ? return postTime;

? ? }

? ? public void setPostTime(Date postTime) {

? ? ? ? this.postTime = postTime;

? ? }

? ? public User getAuthor() {

? ? ? ? return author;

? ? }

? ? public void setAuthor(User author) {

? ? ? ? this.author = author;

? ? }

? ? public String getIpAddr() {

? ? ? ? return ipAddr;

? ? }

? ? public void setIpAddr(String ipAddr) {

? ? ? ? this.ipAddr = ipAddr;

? ? }

?

?

}?

  b.實現序列化的第二種方式為實現接口Externalizable,Externlizable的部分源代碼如下:?

* @see java.io.ObjectInput

?* @see java.io.Serializable

?* @since? ?JDK1.1

?*/

public interface Externalizable extends java.io.Serializable {

? ? /**

? ? ?* The object implements the writeExternal method to save its contents

? ? ?* by calling the methods of DataOutput for its primitive values or?

?首先,我們在序列化對象的時候,由于這個類實現了Externalizable 接口,在writeExternal()方法里定義了哪些屬性可以序列化,

?

哪些不可以序列化,所以,對象在經過這里就把規定能被序列化的序列化保存文件,不能序列化的不處理,然后在反序列的時候自動調?

用readExternal()方法,根據序列順序挨個讀取進行反序列,并自動封裝成對象返回,然后在測試類接收,就完成了反序列。?

?所以說Exterinable的是Serializable的一個擴展。

?

?為了更好的理解相關內容,請看下面的例子:

?

package com.xiaohao.test;

?

import java.io.Externalizable;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInput;

import java.io.ObjectInputStream;

import java.io.ObjectOutput;

import java.io.ObjectOutputStream;

import java.text.SimpleDateFormat;

import java.util.Date;

?

?

/**

?* 測試實體類

?* @author 小浩

?* @創建日期 2015-3-12

?*/

class Person implements Externalizable{

? ? ? ? private static final long serialVersionUID = 1L;<br>? ? String userName;

? ? String password;

? ? String age;

?

?

? ? public Person(String userName, String password, String age) {

? ? ? ? super();

? ? ? ? this.userName = userName;

? ? ? ? this.password = password;

? ? ? ? this.age = age;

? ? }

?

?

? ? public Person() {

? ? ? ? super();

? ? }

?

?

? ? public String getAge() {

? ? ? ? return age;

? ? }

? ? public void setAge(String age) {

? ? ? ? this.age = age;

? ? }

? ? public String getUserName() {

? ? ? ? return userName;

? ? }

? ? public void setUserName(String userName) {

? ? ? ? this.userName = userName;

? ? }

? ? public String getPassword() {

? ? ? ? return password;

? ? }

? ? public void setPassword(String password) {

? ? ? ? this.password = password;

? ? }

?

? ? /**

? ? ?* 序列化操作的擴展類

? ? ?*/

? ? @Override

? ? public void writeExternal(ObjectOutput out) throws IOException {

? ? ? ? //增加一個新的對象

? ? ? ? Date date=new Date();

? ? ? ? out.writeObject(userName);

? ? ? ? out.writeObject(password);

? ? ? ? out.writeObject(date);

? ? }

?

? ? /**

? ? ?* 反序列化的擴展類

? ? ?*/

? ? @Override

? ? public void readExternal(ObjectInput in) throws IOException,

? ? ? ? ? ? ClassNotFoundException {

? ? ? ? //注意這里的接受順序是有限制的哦,否則的話會出錯的

? ? ? ? // 例如上面先write的是A對象的話,那么下面先接受的也一定是A對象...

? ? ? ? userName=(String) in.readObject();

? ? ? ? password=(String) in.readObject();

? ? ? ? SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");

? ? ? ? Date date=(Date)in.readObject();? ? ? ?

? ? ? ? System.out.println("反序列化后的日期為:"+sdf.format(date));

?

? ? }

? ? @Override

? ? public String toString() {

? ? ? ? //注意這里的年齡是不會被序列化的,所以在反序列化的時候是讀取不到數據的

? ? ? ? return "用戶名:"+userName+"密 碼:"+password+"年齡:"+age;

? ? }

}

?

?

/**

?* 序列化和反序列化的相關操作類

?* @author 小浩

?* @創建日期 2015-3-12

?*/

class Operate{

? ? /**

? ? ?* 序列化方法

? ? ?* @throws IOException

? ? ?* @throws FileNotFoundException

? ? ?*/

? ? public void serializable(Person person) throws FileNotFoundException, IOException{

? ? ? ? ObjectOutputStream outputStream=new ObjectOutputStream(new FileOutputStream("a.txt"));

? ? ? ? outputStream.writeObject(person);? ? ??

? ? }

?

? ? /**

? ? ?* 反序列化的方法

? ? ?* @throws IOException

? ? ?* @throws FileNotFoundException

? ? ?* @throws ClassNotFoundException

? ? ?*/

? ? public Person deSerializable() throws FileNotFoundException, IOException, ClassNotFoundException{

? ? ? ? ObjectInputStream ois=new ObjectInputStream(new FileInputStream("a.txt"));

? ? ? ? return (Person) ois.readObject();

? ? }

?

?

?

}

/**

?* 測試實體主類

?* @author 小浩

?* @創建日期 2015-3-12

?*/

public class Test{

? ? public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {

? ? ? ?Operate operate=new Operate();

? ? ? ?Person person=new Person("小浩","123456","20");

? ? ? ?System.out.println("為序列化之前的相關數據如下:\n"+person.toString());

? ? ? ?operate.serializable(person);

? ? ? ?Person newPerson=operate.deSerializable();

? ? ? ?System.out.println("-------------------------------------------------------");

? ? ? ?System.out.println("序列化之后的相關數據如下:\n"+newPerson.toString());

? ? }

?

?

}?

首先,我們在序列化UserInfo對象的時候,由于這個類實現了Externalizable 接口,在writeExternal()方法里定義了哪些屬性可?

以序列化,哪些不可以序列化,所以,對象在經過這里就把規定能被序列化的序列化保存文件,不能序列化的不處理,然后在反序列?

的時候自動調用readExternal()方法,根據序列順序挨個讀取進行反序列,并自動封裝成對象返回,然后在測試類接收,就完成了反?

序列。?

?***對于實現Java的序列化接口需要注意一下幾點:

?

? ? ? ?1.java中的序列化時transient變量(這個關鍵字的作用就是告知JAVA我不可以被序列化)和靜態變量不會被序列

?

? ? ? ? ? 化(下面是一個測試的例子)

?

import java.io.*;

?

class Student1 implements Serializable {

? ? private static final long serialVersionUID = 1L;

? ? private String name;

? ? private transient String password;

? ? private static int count = 0;

?

? ? public Student1(String name, String password) {

? ? ? ? System.out.println("調用Student的帶參的構造方法");

? ? ? ? this.name = name;

? ? ? ? this.password = password;

? ? ? ? count++;

? ? }

?

? ? public String toString() {

? ? ? ? return "人數: " + count + " 姓名: " + name + " 密碼: " + password;

? ? }

}

?

public class ObjectSerTest1 {

? ? public static void main(String args[]) {

? ? ? ? try {

? ? ? ? ? ? FileOutputStream fos = new FileOutputStream("test.obj");

? ? ? ? ? ? ObjectOutputStream oos = new ObjectOutputStream(fos);

? ? ? ? ? ? Student1 s1 = new Student1("張三", "12345");

? ? ? ? ? ? Student1 s2 = new Student1("王五", "54321");

? ? ? ? ? ? oos.writeObject(s1);

? ? ? ? ? ? oos.writeObject(s2);

? ? ? ? ? ? oos.close();

? ? ? ? ? ? FileInputStream fis = new FileInputStream("test.obj");

? ? ? ? ? ? ObjectInputStream ois = new ObjectInputStream(fis);

? ? ? ? ? ? Student1 s3 = (Student1) ois.readObject();

? ? ? ? ? ? Student1 s4 = (Student1) ois.readObject();

? ? ? ? ? ? System.out.println(s3);

? ? ? ? ? ? System.out.println(s4);

? ? ? ? ? ? ois.close();

? ? ? ? } catch (IOException e) {

? ? ? ? ? ? e.printStackTrace();

? ? ? ? } catch (ClassNotFoundException e1) {

? ? ? ? ? ? e1.printStackTrace();

? ? ? ? }

? ? }

}?

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

?

public class Test{

?

?

?

? ? public static void main(String args[]){

?

? ? ? ? try {

?

? ? ? ? ? ? FileInputStream fis = new FileInputStream("test.obj");

? ? ? ? ? ? ObjectInputStream ois = new ObjectInputStream(fis);

?

? ? ? ? ? ? Student1 s3 = (Student1) ois.readObject();

? ? ? ? ? ? Student1 s4 = (Student1) ois.readObject();

?

? ? ? ? ? ? System.out.println(s3);

? ? ? ? ? ? System.out.println(s4);

?

? ? ? ? ? ? ois.close();

? ? ? ? } catch (IOException e) {

? ? ? ? ? ? e.printStackTrace();

? ? ? ? } catch (ClassNotFoundException e1) {

? ? ? ? ? ? e1.printStackTrace();

? ? ? ? }

? ? }

?

?

?

}?

? ? ? ? ? ? 2.也是最應該注意的,如果你先序列化對象A后序列化B,那么在反序列化的時候一定記著JAVA規定先讀到的對象

?

? ? ? ? ? ? ? ?是先被序列化的對象,不要先接收對象B,那樣會報錯.尤其在使用上面的Externalizable的時候一定要注意讀取

?

? ? ? ? ? ? ? ?的先后順序。

?

? ? ? ? ? ? 3.實現序列化接口的對象并不強制聲明唯一的serialVersionUID,是否聲明serialVersionUID對于對象序列化的向

?

? ? ? ? ? ? ? 上向下的兼容性有很大的影響。我們來做個測試:

?

思路一? 把User中的serialVersionUID去掉,序列化保存。反序列化的時候,增加或減少個字段,看是否成功。? Java代碼?

public class User implements Serializable{

?

private String name;

?

?private int age;

?

private long phone;

?

private List<UserVo> friends;

?

...<br>}?

保存到文件中:?

Java代碼

ByteArrayOutputStream bos = new ByteArrayOutputStream();

ObjectOutputStream os = new ObjectOutputStream(bos);

os.writeObject(src);

os.flush();

os.close();

byte[] b = bos.toByteArray();

bos.close();

FileOutputStream fos = new FileOutputStream(dataFile);

fos.write(b);

fos.close();?

增加或者減少字段后,從文件中讀出來,反序列化:?

Java代碼

ByteArrayOutputStream bos = new ByteArrayOutputStream();

ObjectOutputStream os = new ObjectOutputStream(bos);

os.writeObject(src);

os.flush();

os.close();

byte[] b = bos.toByteArray();

bos.close();

FileOutputStream fos = new FileOutputStream(dataFile);

fos.write(b);

fos.close();?

結果:拋出異常信息? Java代碼?

Exception in thread "main" java.io.InvalidClassException: serialize.obj.UserVo; local class incompatible: stream classdesc serialVersionUID = 3305402508581390189, local class serialVersionUID = 7174371419787432394 at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:560)

at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1582)

at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1495)

at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731)

at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)

at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)

at serialize.obj.ObjectSerialize.read(ObjectSerialize.java:74)

at serialize.obj.ObjectSerialize.main(ObjectSerialize.java:27)

  ?

思路二? eclipse指定生成一個serialVersionUID,序列化保存,修改字段后反序列化? 略去代碼? 結果:反序列化成功? 結論? 如果沒有明確指定serialVersionUID,序列化的時候會根據字段和特定的算法生成一個serialVersionUID,當屬性有變化時這個id發生了變化,所以反序列化的時候? 就會失敗。拋出“本地classd的唯一id和流中class的唯一id不匹配”。? jdk文檔關于serialVersionUID的描述:? 寫道? 如果可序列化類未顯式聲明 serialVersionUID,則序列化運行時將基于該類的各個方面計算該類的默認 serialVersionUID 值,如“Java(TM) 對象序列化規范”中所述。不過,強烈建議 所有可序列化類都顯式聲明 serialVersionUID 值,原因是計算默認的 serialVersionUID 對類的詳細信息具有較高的敏感性,根據編譯器實現的不同可能千差萬別,這樣在反序列化過程中可能會導致意外的 InvalidClassException。因此,為保證 serialVersionUID 值跨不同 java 編譯器實現的一致性,序列化類必須聲明一個明確的 serialVersionUID 值。還強烈建議使用 private 修飾符顯示聲明 serialVersionUID(如果可能),原因是這種聲明僅應用于直接聲明類 – serialVersionUID 字段作為繼承成員沒有用處。數組類不能聲明一個明確的 serialVersionUID,因此它們總是具有默認的計算值,但是數組類沒有匹配 serialVersionUID 值的要求。?

三.實現序列化的其它方式 (這是一個擴展內容,感興趣的可以擴展一下)??

? ?1)是把對象包裝成JSON字符串傳輸。

?

? ? ?這里采用JSON格式同時使用采用Google的gson-2.2.2.jar 進行轉義

?

? 2)采用谷歌的ProtoBuf

?

? ? ?隨著Google工具protoBuf的開源,protobuf也是個不錯的選擇。對JSON,Object Serialize(Java的序列化和反序列化),

?

? ? ?ProtoBuf 做個對比。

?

? ? ?定義一個通用的待傳輸的對象UserVo:

?

public class User

<span style="white-space: pre;">private static final long serialVersionUID = -5726374138698742258L;</span>

{ private String name;

? private int age;

? private long phone;

? private List<User> friends;

?...set和get方法

?}

 ?

初始化User的實例src:?

User user1 = new UserVo();

user1 .setName("user1 ");

?user1 .setAge(30);

?user1 .setPhone(13789126278L);

?UserVo f1 = new UserVo();

?f1.setName("tmac");

?f1.setAge(32);

?f1.setPhone(123L);

?User user2 = new User();

?user2 .setName("user2 ");

?user2 .setAge(29);

?user2 .setPhone(123L); <br> List<User> friends = new ArrayList<User>();

?friends.add(user1 );

?friends.add(user2 );

?user1 .setFriends(friends);?

1.首先使用JOSN來實現序列化。?

Gson gson = new Gson();<br>String json = gson.toJson(src);?

得到的字符串:?

{"name":"user1 ","age":30,"phone":123,"friends":[{"name":"user1 ","age":32,"phone":123},{"name":"user2 ","age":29,"phone":123}]}?

字節數為153? Json的優點:明文結構一目了然,可以跨語言,屬性的增加減少對解析端影響較小。缺點:字節數過多,依賴于不同的第三方類庫。?

Object Serialize(Java的序列化和反序列化)? UserVo實現Serializalbe接口,提供唯一的版本號:? 序列化方法:?

ByteArrayOutputStream bos = new ByteArrayOutputStream();

ObjectOutputStream os = new ObjectOutputStream(bos);

os.writeObject(src);

os.flush();

os.close();

byte[] b = bos.toByteArray();

bos.close();?

字節數是238?

反序列化:?

ObjectInputStream ois = new ObjectInputStream(fis);

vo = (UserVo) ois.readObject();

ois.close();

fis.close();?

Object Serializalbe 優點:java原生支持,不需要提供第三方的類庫,使用比較簡單。? 缺點:無法跨語言,字節數占用比較大,某些情況下對于對象屬性的變化比較敏感。? 對象在進行序列化和反序列化的時候,必須實現Serializable接口,但并不強制聲明唯一的serialVersionUID? 是否聲明serialVersionUID對于對象序列化的向上向下的兼容性有很大的影響。?

Google ProtoBuf? protocol buffers 是google內部得一種傳輸協議,目前項目已經開源(http://code.google.com/p/protobuf/)。? 它定義了一種緊湊得可擴展得二進制協議格式,適合網絡傳輸,并且針對多個語言有不同得版本可供選擇。? 以protobuf-2.5.0rc1為例,準備工作:? 下載源碼,解壓,編譯,安裝? Shell代碼? tar zxvf protobuf-2.5.0rc1.tar.gz ./configure ./make ./make install? 測試:? Shell代碼? MacBook-Air:~ ming$ protoc –version libprotoc 2.5.0? 安裝成功!? 進入源碼得java目錄,用mvn工具編譯生成所需得jar包,protobuf-java-2.5.0rc1.jar?

1、編寫.proto文件,命名UserVo.proto?

?

package serialize;

option java_package = "serialize";

option java_outer_classname="UserVoProtos";

message User{

optional string name = 1;

optional int32 age = 2;

optional int64 phone = 3;

repeated serialize.UserVo friends = 4;

?

}?

2、在命令行利用protoc 工具生成builder類? Shell代碼? protoc -IPATH=.proto文件所在得目錄 –java_out=java文件的輸出路徑 .proto的名稱? 得到UserProtos類?

3、編寫序列化代碼?

UserVoProtos.User.Builder builder = UserVoProtos.User.newBuilder();

builder.setName("Yaoming"); builder.setAge(30);

builder.setPhone(13789878978L);

UserVoProtos.UserVo.Builder builder1 = UserVoProtos.UserVo.newBuilder();

builder1.setName("tmac"); builder1.setAge(32); builder1.setPhone(138999898989L);

UserVoProtos.UserVo.Builder builder2 = UserVoProtos.UserVo.newBuilder();

builder2.setName("liuwei"); builder2.setAge(29); builder2.setPhone(138999899989L);

builder.addFriends(builder1);

builder.addFriends(builder2);

UserVoProtos.UserVo vo = builder.build();? byte[] v = vo.toByteArray();?

字節數53? 反序列化?

UserVoProtos.UserVo uvo = UserVoProtos.UserVo.parseFrom(dstb);

System.out.println(uvo.getFriends(0).getName());?

結果:tmac,反序列化成功? google protobuf 優點:字節數很小,適合網絡傳輸節省io,跨語言 。? 缺點:需要依賴于工具生成代碼。?

工作機制? proto文件是對數據的一個描述,包括字段名稱,類型,字節中的位置。protoc工具讀取proto文件生成對應builder代碼的類庫。protoc xxxxx –java_out=xxxxxx 生成java類庫。builder類根據自己的算法把數據序列化成字節流,或者把字節流根據反射的原理反序列化成對象。官方的示例:https://developers.google.com/protocol-buffers/docs/javatutorial。? proto文件中的字段類型和java中的對應關系:? 詳見:https://developers.google.com/protocol-buffers/docs/proto? .proto Type java Type c++ Type? double double double? float float float? int32 int int32? int64 long int64? uint32 int uint32? unint64 long uint64? sint32 int int32? sint64 long int64? fixed32 int uint32? fixed64 long uint64? sfixed32 int int32? sfixed64 long int64? bool boolean bool? string String string? bytes byte string? 字段屬性的描述:? 寫道? required: a well-formed message must have exactly one of this field. optional: a well-formed message can have zero or one of this field (but not more than one). repeated: this field can be repeated any number of times (including zero) in a well-formed message. The order of the repeated values will be preserved.? protobuf 在序列化和反序列化的時候,是依賴于.proto文件生成的builder類完成,字段的變化如果不表現在.proto文件中就不會影響反序列化,比較適合字段變化的情況。? 做個測試:把UserVo序列化到文件中:?

UserProtos.User vo = builder.build();

byte[] v = vo.toByteArray();

FileOutputStream fos = new FileOutputStream(dataFile);

fos.write(vo.toByteArray());

fos.close();

?

?

為User增加字段,對應的.proto文件:

?

Text代碼

?

package serialize;

option java_package = "serialize";

option java_outer_classname="UserVoProtos";

message User{

optional string name = 1;

optional int32 age = 2;

optional int64 phone = 3;

repeated serialize.UserVo friends = 4;

optional string address = 5; }

?

?

?

從文件中反序列化回來:

?

Java代碼

FileInputStream fis = new FileInputStream(dataFile);

byte[] dstb = new byte[fis.available()];

for(int i=0;i<dstb.length;i++){ dstb[i] = (byte)fis.read(); }

fis.close(); UserProtos.User uvo = UserProtos.User.parseFrom(dstb);

System.out.println(uvo.getFriends(0).getName());?

從文件中反序列化回來:?

Java代碼?

FileInputStream fis = new FileInputStream(dataFile);

byte[] dstb = new byte[fis.available()];

for(int i=0;i<dstb.length;i++){ dstb[i] = (byte)fis.read(); }

fis.close(); UserProtos.User uvo = UserProtos.User.parseFrom(dstb);

System.out.println(uvo.getFriends(0).getName());?

成功得到結果。?

三種方式對比傳輸同樣的數據,google protobuf只有53個字節是最少的。結論:?

方式 優點 缺點? JSON? 跨語言、格式清晰一目了然? 字節數比較大,需要第三方類庫? Object Serialize java原生方法不依賴外部類庫 字節數比較大,不能跨語言? Google protobuf? 跨語言、字節數比較少? 編寫.proto配置用protoc工具生成對應的代碼

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/540264.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/540264.shtml
英文地址,請注明出處:http://en.pswp.cn/news/540264.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

nginx 非80、443端口跳轉到80、443

其實很簡單: 123if ($server_port ! 80 ) { rewrite ^/(.*)$ http://$host/$1 permanent; }舉一反三。。。 123if ($server_port ! 443 ) { rewrite ^/(.*)$ https://$host/$1 permanent; }123if ($host ! host ) { rewrite ^/(.*)$ http://host/$1 permanent; }本文轉自 ninny…

[轉載] 一文徹底搞懂父類引用指向子類對象問題

參考鏈接&#xff1a; 用子類引用子類對象 vs 父類引用 public class Father { private String name; private int age; private int weight; public void eat() { System.out.println("Father is eating"); } private void run() { System.out.println("Runin…

把控站外seo效果的幾個操作點

把控站外seo效果的幾個操作點 實際上&#xff0c;站外的seo不僅僅是外鏈這么簡單&#xff0c;還包括用戶行為&#xff08;點擊&#xff09;&#xff0c;品牌詞曝光等工作。大部分情況下&#xff0c;我們所說的站外優化就是發外鏈。本文就外鏈相關事宜&#xff0c;講解些許操作點…

[轉載] 【C語言】fopen C4996錯誤解決

參考鏈接&#xff1a; C和C#重載可以與繼承一起使用嗎 C4996 fopen: This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. 解決方案&#xff1a;添加宏定…

Quartus II 8.1 詳解--有圖---圖片詳解 【1講】

Quartus II 8.1 詳解--有圖---圖片詳解 看圖片比較清楚&#xff0c;比文章清楚的多 本文轉自 zhangguangyi 51CTO博客&#xff0c;原文鏈接http://blog.51cto.com/bosszhang/808019:

[轉載] JAVA數組實現學生成績統計

參考鏈接&#xff1a; Java程序的輸出 20(繼承) 一、項目名稱 數組實現學生成績統計 二、項目描述 1.項目簡介&#xff1a; 由用戶輸入學生人數與名字&#xff0c;并定義當前學期課程數與課程名&#xff0c;并分別錄入每位學生每門課程成績&#xff0c;系統顯示輸入每位學生每…

建立同步文件的腳本

為避免一個一個的去修改每一個服務器的配置文件&#xff0c;只需要rsync同步一下就可以搞定#!/bin/bash#rsync.shLOCAL_DIR"/opt/admin"test -n "$hosts" || hosts"xxxx xxxx"REMOTE_DIR"/opt/"RSYNC_LOG"/opt/var/log/rsync.log…

[轉載] Java三元運算符示例

參考鏈接&#xff1a; Java中的運算符 本示例說明如何編寫Java三元運算符。 這是語法 condition ? get_this_if_true : get_this_if_false Java三元運算符語法 (n > 18) ? true : false; (n true) ? 1 : 0; (n null) ? n.getValue() : 0; 1. Java三元運算符 …

shell下的進度條和最大最小平均值

進度條 C語言下的進度條參考我原來的一篇blog->進度條 1234567891011121314151617181920212223function proc() {i0 str arr(| / - \\) index0 while [ $i -le 100 ] do printf "[%-101s][%d%%][%c]\r" "$str" "$i" "${arr[$index]}&qu…

[轉載] 你真的會用 Java 中的三目運算符嗎

參考鏈接&#xff1a; Java中的按位運算符 轉載:http://blog.jobbole.com/93511/ 寫在前面&#xff1a; 三目運算符是我們經常在代碼中使用的&#xff0c;a (bnull?0:1); 這樣一行代碼可以代替一個 if-else&#xff0c;可以使代碼變得清爽易讀。但是&#xff0c;三目運算符也…

HTTP Keep-Alive模式

1、什么是Keep-Alive模式&#xff1f; 我們知道HTTP協議采用“請求-應答”模式&#xff0c;當使用普通模式&#xff0c;即非KeepAlive模式時&#xff0c;每個請求/應答客戶和服務器都要新建一個連接&#xff0c;完成 之后立即斷開連接&#xff08;HTTP協議為無連接的協議&#…

[轉載] java:比較運算符

參考鏈接&#xff1a; Java中的new運算符 1.compareTo()方法: compareTo()方法返回的是一個int類型值. //聲明的值 BigDecimal t_sell1 new BigDecimal(); BigDecimal t_sell2 new BigDecimal(); if(t_sell1.compareTo(t_sell2)0){ return "t_sell1的值等于t_sell2&…

[轉載] java左移右移和無符號右移

參考鏈接&#xff1a; Java中的按位右移運算符 ###知識點 java的三種位移運算符&#xff1a; <<&#xff1a;左移運算符&#xff0c;num << 1,相當于num乘以2 >>&#xff1a;右移運算符&#xff0c;num >> 1,相當于num除以2 >>>&#xff1a…

Script:List OBJECT DEPENDENT

以下腳本用以列出數據庫中對象的依賴性:select D_OBJ#, 本文轉自maclean_007 51CTO博客&#xff0c;原文鏈接: http://blog.51cto.com/maclean/1276767

[轉載] java避免空指針異常_第1部分:在現代Java應用程序中避免空指針異常

參考鏈接&#xff1a; Java的instanceof及其應用 java避免空指針異常 空做與不做 (Null do’s and don’ts) In the talk Null References: The Billion Dollar Mistake, Sir Tony Hoare describes implementing null references as a part of the ALGOL programming languag…

[轉載] 什么是Java中的自動拆裝箱 integer

參考鏈接&#xff1a; Java中autoboxing自動裝箱整數對象的比較 本文主要介紹Java中的自動拆箱與自動裝箱的有關知識。 1、基本數據類型 基本類型&#xff0c;或者叫做內置類型&#xff0c;是Java中不同于類(Class)的特殊類型。它們是我們編程中使用最頻繁的類型。 Jav…

[轉載] python常用庫

參考鏈接&#xff1a; Python–新一代語言 轉載至&#xff1a;https://www.cnblogs.com/jiangchunsheng/p/9275881.html 今天我將介紹20個屬于我常用工具的Python庫&#xff0c;我相信你看完之后也會覺得離不開它們。他們是&#xff1a; Requests.Kenneth Reitz寫的最富盛…

linux下安裝配置oracle

檢查系統是否已安裝所需的開發包 使用rpm -qa命令&#xff0c;確保以下包已成功安裝。對于包的版本,只有版本高于下面的都可以,如果低于此版本,則要升級處理,如下: binutils-2.15.92.0.2-13.EL4 compat-db-4.1.25-9 compat-libstdc-296-2.96-132.7.2 control-center-2.8.0-12 g…

[轉載] c++多態與java多態性_Java中的多態性

參考鏈接&#xff1a; Java中的加法和串聯 c多態與java多態性 Polymorphism is one of the core concepts of OOPS paradigm. The meaning of polymorphism is the condition of occurring in several different forms. 多態是OOPS范式的核心概念之一。 多態性的含義是以幾種不…

USB peripherals can turn against their users

Turning USB peripherals into BadUSB USB devices are connected to – and in many cases even built into – virtually all computers. The interface standard conquered the world over the past two decades thanks to its versatility: Almost any computer peripheral…