版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第7章對(duì)象序列化
7.1對(duì)象序列化7.2序列化操作7.3定制序列化
7.1對(duì)?象?序?列?化
7.1.1序列化的概念
計(jì)算機(jī)軟件的主要工作是處理數(shù)據(jù)。在處理數(shù)據(jù)時(shí),經(jīng)常會(huì)遇到需要處理一組相關(guān)的數(shù)據(jù),例如,要保存這樣一條聊天信息“張三:李四:你好”,這條信息中包括三個(gè)內(nèi)容,即發(fā)信者、接收者和聊天內(nèi)容,通常需要使用三個(gè)變量進(jìn)行存儲(chǔ)。在C語言中使用結(jié)構(gòu)體實(shí)現(xiàn)儲(chǔ)存一組相關(guān)的數(shù)據(jù),如例7-1所示。
【例7-1】
使用結(jié)構(gòu)體存儲(chǔ)數(shù)據(jù)。
StructMessage{
charsender[10];
charreceiver[10];
charcontent[30];
}msg[20];
【例7-2】利用結(jié)構(gòu)體存儲(chǔ)一組數(shù)據(jù),并保存在文件中或者從文件中讀取。
Filefp=File();
//存儲(chǔ)的方法
for(i=0;i<20;i++)
fwrite(&msg[i],sizeof(StructMessage),1,fp);
//讀取的方法
for(i=0;i<20;i++)
fread(&msg[i],sizeof(StructMessage),1,fp);
Java語言中,取消了結(jié)構(gòu)體,除了基本數(shù)據(jù)類型都是對(duì)象。如果要存儲(chǔ)一組相關(guān)的數(shù)據(jù),就必須采用自定義相關(guān)類。
【例7-3】使用Java定義存儲(chǔ)消息的類。對(duì)比兩種語言對(duì)聊天消息的描述方法,其主要區(qū)別在于,使用Java語言描述方式不僅包含成員變量,而且包括了成員方法,從而實(shí)現(xiàn)了信息的封裝。
在Java語言中,處理數(shù)據(jù)均采用流的方式,其最大的特點(diǎn)就是數(shù)據(jù)的輸入和輸出都按順序進(jìn)行。Java語言是面向?qū)ο蟮恼Z言,除了字符串對(duì)象可以通過writeUTF()和readUTF()直接操作外,其他對(duì)象不能直接存儲(chǔ)和通過網(wǎng)絡(luò)發(fā)送。當(dāng)需要對(duì)使用例7-3的類所定義的實(shí)例對(duì)象進(jìn)行存儲(chǔ)或者發(fā)送時(shí),就應(yīng)該將該對(duì)象進(jìn)行序列化操作,使其轉(zhuǎn)變?yōu)榱餍问?,然后才能?shí)現(xiàn)存儲(chǔ)和通過網(wǎng)絡(luò)發(fā)送。序列化是一種用來處理對(duì)象流的機(jī)制,對(duì)象流是將對(duì)象的內(nèi)容進(jìn)行流化,然后將經(jīng)過流化后的對(duì)象進(jìn)行讀/寫操作和用于網(wǎng)絡(luò)傳輸。發(fā)送端將對(duì)象序列化為流,接收端反序列化從數(shù)據(jù)流重新構(gòu)造對(duì)象,保證了對(duì)象的完整性和可傳遞性。即,序列化的過程是將對(duì)象寫入字節(jié)流,反序列化的過程是從字節(jié)流中讀取對(duì)象。將對(duì)象狀態(tài)轉(zhuǎn)換成字節(jié)流之后,可以用java.io包中的各種字節(jié)流類將其保存到文件中,或者通過管道在線程之間傳輸,或者通過網(wǎng)絡(luò)連接將對(duì)象數(shù)據(jù)發(fā)送到另一主機(jī)。
序列化在網(wǎng)絡(luò)程序設(shè)計(jì)(如Socket、RMI(RemoteMethodInvocation)、JMS(JavaMessageService)、EJB(EnterpriseJavaBean))中有廣泛的應(yīng)用。7.1.2序列化的實(shí)現(xiàn)
對(duì)象序列化是將攜帶信息的對(duì)象轉(zhuǎn)換為可以用于存儲(chǔ)或傳輸形式的過程。在序列化期間,對(duì)象將其當(dāng)前狀態(tài)寫入到臨時(shí)或持久性存儲(chǔ)區(qū),然后,可以通過從存儲(chǔ)區(qū)中讀取或反序列化對(duì)象的狀態(tài),重新創(chuàng)建該對(duì)象。序列化分為兩大部分:序列化和反序列化,即對(duì)象序列化不僅要將對(duì)象轉(zhuǎn)換成字節(jié)表示,有時(shí)還要恢復(fù)對(duì)象。
序列化是這個(gè)過程的第一部分,將數(shù)據(jù)分解成字節(jié)流,以便存儲(chǔ)在文件中或在網(wǎng)絡(luò)上傳輸。反序列化就是打開字節(jié)流,按照被恢復(fù)數(shù)據(jù)的對(duì)象實(shí)例重構(gòu)對(duì)象。這兩個(gè)過程結(jié)合起來,就可以輕松地存儲(chǔ)和傳輸對(duì)象數(shù)據(jù)。序列化的目的:
●?以某種存儲(chǔ)形式使自定義對(duì)象持久化;
●?將對(duì)象從一個(gè)地方傳遞到另一個(gè)地方;
●?使程序更具維護(hù)性。
Java序列化是基于TCP協(xié)議的,實(shí)現(xiàn)比較簡(jiǎn)單,通常不需要編寫保存和恢復(fù)對(duì)象狀態(tài)的定制代碼。但是要求被序列化的類是實(shí)現(xiàn)了java.io.Serializable接口的,這樣就可以轉(zhuǎn)換成字節(jié)流或從字節(jié)流恢復(fù),不需要在類中增加額外任何代碼。Serializable接口定義如圖7-1所示。圖7-1Serializable接口定義
在Serinalizable接口中未提供任何方法,即不存在需要被覆蓋的方法。通過implements實(shí)現(xiàn)Serializable接口的目的在于標(biāo)識(shí)該對(duì)象是可被序列化的。
在Java語言中并不是任何個(gè)類都可被序列化。通常將用于存儲(chǔ)信息的類進(jìn)行序列化,因?yàn)檫@些類所定義的對(duì)象是用于存儲(chǔ)和傳輸?shù)?,例如學(xué)生信息類、消息信息類。而用于執(zhí)行指令和操作的類是不用于序列化的,例如將學(xué)生信息儲(chǔ)存和讀取類、消息的發(fā)送和接收類。尤其要注意,涉及線程的類和與特定JVM有非常復(fù)雜關(guān)系的類,都不能進(jìn)行序列化操作。序列化使其他代碼可以查看或修改那些不序列化便無法訪問的對(duì)象實(shí)例數(shù)據(jù)。確切地說,代碼執(zhí)行序列化需要特殊的權(quán)限,即指定了SerializationFormatter標(biāo)志的Security?Permission。在默認(rèn)策略下,通過Internet下載的代碼或Intranet代碼不會(huì)授予該權(quán)限;只有本地計(jì)算機(jī)上的代碼才被授予該權(quán)限。
通常,實(shí)現(xiàn)Serializable接口的類所聲明的對(duì)象實(shí)例中所有字段都會(huì)被序列化,這意味著數(shù)據(jù)會(huì)被表示為實(shí)例的序列化數(shù)據(jù)。這樣能夠解釋該格式的代碼有可能能夠確定這些數(shù)據(jù)的值,而不依賴于該成員的可訪問性。類似地,反序列化從序列化的表示形式中提取數(shù)據(jù),并直接設(shè)置對(duì)象狀態(tài),這也與可訪問性規(guī)則無關(guān)。7.1.3ObjectInputStream與ObjectOutputStream
為了將存儲(chǔ)于對(duì)象中的數(shù)據(jù)保存在磁盤文件或通過網(wǎng)絡(luò)發(fā)送等,需要使用基于對(duì)象的輸入/輸出流。java.io包提供兩個(gè)類用于序列化對(duì)象傳輸,分別是對(duì)象輸入類ObjectInput?Stream與對(duì)象輸出流類ObjectOutputStream。
ObjectInputStream用于從底層輸入流中讀取對(duì)象類型的數(shù)據(jù),ObjectOutputStream用于將對(duì)象類型的數(shù)據(jù)寫入到底層輸入流。ObjectInputStream與ObjectOutputStream類所讀/寫的對(duì)象必須實(shí)現(xiàn)了Serializable接口。對(duì)象中被transient和static修飾的成員變量不會(huì)被讀取和寫入。●?ObjectInputStream從字節(jié)流重構(gòu)對(duì)象,實(shí)現(xiàn)反序列化過程。反序列化時(shí),JVM用頭信息生成對(duì)象實(shí)例,然后將對(duì)象字節(jié)流中的數(shù)據(jù)復(fù)制到對(duì)象數(shù)據(jù)成員中。
●?ObjectOutputStream負(fù)責(zé)將對(duì)象寫入字節(jié)流,實(shí)現(xiàn)序列化過程,該序列化過程與字節(jié)流連接,包括對(duì)象類型和版本信息。
用一個(gè)輸出流(如FileOutputStream)來構(gòu)造一個(gè)ObjectOutputStream(對(duì)象流)對(duì)象,接著,使用ObjectOutputStream對(duì)象的writeObject(Objectobj)方法就可以將參數(shù)為obj的對(duì)象寫出(即保存其狀態(tài)),要恢復(fù)的話則用輸入流。當(dāng)需要將數(shù)據(jù)存儲(chǔ)在本地磁盤時(shí),在Java中需要使用ObjectOutputStream類,該類擴(kuò)展DataOutput接口。writeObject()方法是最重要的方法,用于對(duì)象序列化。如果對(duì)象包含其他對(duì)象的引用,則writeObject()方法遞歸序列化這些對(duì)象。由于writeObject()可以序列化整組交叉引用的對(duì)象,因此,同一ObjectOutputStream實(shí)例可能不小心被請(qǐng)求序列化同一對(duì)象。每個(gè)ObjectOutputStream維護(hù)序列化的對(duì)象引用表,防止發(fā)送同一對(duì)象的多個(gè)拷貝。
【例7-4】
在文件tmp中保存兩個(gè)對(duì)象,其中一個(gè)是字符串“Today”,另一個(gè)是當(dāng)前的日期。//
序列化
today's
?date
到一個(gè)文件中.
FileOutputStream
f
=
new
FileOutputStream("tmp");
ObjectOutputStream
s
=
new
ObjectOutputStream(f);
s.writeObject("Today");
s.writeObject(new
Date());
s.flush();
當(dāng)需要將數(shù)據(jù)從本地磁盤讀取出時(shí),在Java中需要使用ObjectInputStream類,該類擴(kuò)展DataInput接口。readObject()為重要的方法,實(shí)現(xiàn)從字節(jié)流中反序列化對(duì)象。每次調(diào)用readObject()方法都返回流中下一個(gè)Object。對(duì)象字節(jié)流并不傳輸類的字節(jié)碼,而是包括類名及其簽名。readObject()收到對(duì)象時(shí),JVM裝入頭中指定的類。如果找不到這個(gè)類,則readObject()拋出ClassNotFoundException。如果需要傳輸對(duì)象數(shù)據(jù)和字節(jié)碼,則可以用RMI框架。ObjectInputStream的其余方法用于定制反序列化過程。
【例7-5】從文件tmp中讀取數(shù)據(jù)對(duì)象。
//從文件中反序列化
string
對(duì)象和
date
對(duì)象
FileInputStream
in
=
new
FileInputStream(“tmp”);
ObjectInp
utStream
s
=
new
ObjectInputStream(in);
String
today
=
(String)s.readObject();
Date
date
=
(Date)s.readObject();
7.2序?列?化?操?作
7.2.1序列化存儲(chǔ)
通常,實(shí)現(xiàn)序列化接口的類是用于存儲(chǔ)和傳輸?shù)念悾糜诓僮鞯念愂遣贿M(jìn)行序列化的。首先,通過代碼學(xué)習(xí)在Java中如何通過序列化實(shí)現(xiàn)聊天信息的儲(chǔ)存。在下面的例子中定義一個(gè)聊天信息類,該類用于存儲(chǔ)信息,需要實(shí)現(xiàn)Serializable接口。并且該類需要在存儲(chǔ)和讀取時(shí)都使用,通常將自定義信息類、存儲(chǔ)類和讀取類設(shè)計(jì)在一個(gè)包中,否則會(huì)出現(xiàn)無法找到類的異常發(fā)生。代碼注釋如下:
①第1行通常為了保證能夠順利地進(jìn)行序列化和反序列化操作,聲明為Serializable接口的存儲(chǔ)類和實(shí)現(xiàn)操作類應(yīng)在一個(gè)message包中,以保證訪問的路徑;
②第3行定義的存儲(chǔ)類實(shí)現(xiàn)了Serializable接口;
③第4~6行聲明了三個(gè)成員變量;
④第7~11行聲明了構(gòu)造方法;
⑤第12~16行定義了輸出方法show()。
例7-6中定義的信息類需要實(shí)現(xiàn)Serializable接口,所以需要引用io類庫(kù)。在類中的成員變量有三個(gè),分別記錄消息的發(fā)送者、接收者和內(nèi)容。成員方法有兩個(gè),一個(gè)是用于賦初值的構(gòu)造方法Message(),另一個(gè)是用于輸出顯示的方法show()。接下來,定義將該類進(jìn)行存儲(chǔ)操作的類,即進(jìn)行序列化操作的類。該類中首先申明了兩個(gè)需要被存儲(chǔ)的信息對(duì)象,然后申明文件輸出對(duì)象,通過ObjectOutputStream.write
Object()方法,將信息對(duì)象保存到文件中。
【例7-7】
定義用于存儲(chǔ)學(xué)生信息的類,執(zhí)行序列化操作,保存數(shù)據(jù)至文件。
代碼注釋如下:
①第1行與實(shí)現(xiàn)序列化的存儲(chǔ)類在一個(gè)message包中;
②第9~10行使用Message類聲明了兩個(gè)被存儲(chǔ)對(duì)象;
③第12~13行聲明對(duì)象輸出流;
④第14~15行通過writeOjbect()輸出對(duì)象,實(shí)現(xiàn)序列化操作。
運(yùn)行該程序,將在當(dāng)前目錄下生成一個(gè)新的文件msgDB.dat,用于存儲(chǔ)信息。使用記事本軟件打開該文件,可以看到存儲(chǔ)的內(nèi)容,如圖7-2所示。圖7-2msgDB.dat文件內(nèi)容
【例7-8】
定義用于存儲(chǔ)信息的類,執(zhí)行反序列化操作,從文件中讀取數(shù)據(jù)還原成對(duì)象。
代碼注釋如下:
①第1行與實(shí)現(xiàn)序列化的存儲(chǔ)類在一個(gè)message包中;
②第9~10行聲明對(duì)象輸入流;
③第12~13行采用readObject()實(shí)現(xiàn)反序列化操作,因?yàn)樽x取時(shí)默認(rèn)類型為Object,所以需要進(jìn)行一次強(qiáng)制類型轉(zhuǎn)換為需要的類對(duì)象;
④第16~17行輸出內(nèi)容。
程序運(yùn)行結(jié)果如圖7-3所示。圖7-3反序列化結(jié)果7.2.2序列化傳輸
序列化操作不僅可以在本地磁盤保存類數(shù)據(jù),也可以將對(duì)象用于網(wǎng)絡(luò)傳輸。首先,定義一個(gè)用于存儲(chǔ)消息的消息類,用于記錄消息發(fā)送者、消息接收者、消息內(nèi)容,在這里直接利用了例7-6,注意Message類的包信息需要進(jìn)行相應(yīng)修改。另外分別編寫客戶端和服務(wù)器端程序。
【例7-9】實(shí)現(xiàn)客戶端,用于序列化對(duì)象,發(fā)送對(duì)象流。代碼注釋如下:
①第9行通過TCP連接指定的服務(wù)器localhost的8080端口;
②第10行套接字上獲得輸出流,使其作為對(duì)象輸出流的參數(shù);
③第11行準(zhǔn)備要傳輸?shù)膶?duì)象;
④第12~13行通過writeObject()發(fā)送信息對(duì)象。
【例7-10】
實(shí)現(xiàn)服務(wù)器端,用于接收對(duì)象流,進(jìn)行反序列化操作。代碼注釋如下:
①第10行啟動(dòng)本地的TCP8080端口,監(jiān)聽客戶端的連接請(qǐng)求;
②第12行與客戶端實(shí)現(xiàn)連接;
③第13行獲得套接字的getInputStream(),使其作為ObjectInputStream的參數(shù);
④第15行獲得對(duì)象,并進(jìn)行反序列化操作,還原為Message對(duì)象;
⑤第16~17行輸出結(jié)果。
服務(wù)器端接收序列化及反序列化操作運(yùn)行結(jié)果如圖7-4所示。圖7-4服務(wù)器端運(yùn)行結(jié)果從運(yùn)行結(jié)果可見,服務(wù)器收到的信息對(duì)象直接輸出是不可讀的,除非該信息類中覆蓋了Object中的toString()方法。
7.3定?制?序?列?化
7.3.1序列化成員變量
在Java中類的成員變量可以是簡(jiǎn)單數(shù)據(jù)類型,也可以是復(fù)雜數(shù)據(jù)類型,如字符串類類型、自定義類類型等。當(dāng)某個(gè)類實(shí)現(xiàn)了序列化接口時(shí),其未加transient和static修飾的成員變量一同被序列化。所以,當(dāng)使用類類型定義成員變量時(shí),要保證這些類是可以被序列化的,即實(shí)現(xiàn)了Serializable接口。如String類的定義中就聲明實(shí)現(xiàn)了Serializable接口,如圖7-5所示。圖7-5String類的定義當(dāng)實(shí)現(xiàn)序列化的自定義類的成員變量中還包含了其他的自定義類對(duì)象時(shí),就需要該成員變量實(shí)現(xiàn)序列化接口。
代碼注釋如下:
①第6行使用Detail類對(duì)象作為成員變量;
②第20~27行實(shí)現(xiàn)Detail類的定義,此時(shí)它未實(shí)現(xiàn)Serializable接口。
可以從以上代碼可以看出,新定義了Details類,用于存儲(chǔ)消息內(nèi)容和發(fā)送時(shí)間,但是該類未實(shí)現(xiàn)序列化接口。在Message類中,采用Details類定義了一個(gè)details對(duì)象。在對(duì)此類進(jìn)行編譯時(shí),未出現(xiàn)任何錯(cuò)誤提示。
在運(yùn)行對(duì)象流發(fā)送端時(shí)將會(huì)拋出異常,提示Details類未實(shí)現(xiàn)Serializable接口,如圖7-6所示??梢娨粋€(gè)實(shí)現(xiàn)序列化接口中的成員變量如果是類對(duì)象,那么該類也必須實(shí)現(xiàn)了序列化接口,否則在運(yùn)行時(shí)就會(huì)出現(xiàn)無法實(shí)現(xiàn)序列化操作的異常提示信息。圖7-6異常提示信息7.3.2定制序列化
對(duì)于一個(gè)正在運(yùn)行的類對(duì)象來說,存在以下概念:
●?生命周期:從JVM提供一個(gè)對(duì)象所需要的資源,到釋放該對(duì)象資源為止,就是一個(gè)對(duì)象的生命周期。
●?短暫存儲(chǔ):對(duì)象在內(nèi)存中構(gòu)建后,會(huì)隨著程序的運(yùn)行和結(jié)束而改變和結(jié)束,這就是短暫存儲(chǔ)。在Java語言中,序列化過程中,使用transient關(guān)鍵字表示屬性或?qū)ο笫嵌虝旱摹?/p>
●?永久存儲(chǔ):對(duì)象被保存在永久設(shè)備中,這些永久設(shè)備包括文件、磁盤、數(shù)據(jù)庫(kù)等,該對(duì)象數(shù)據(jù)不會(huì)隨程序結(jié)束而消失。對(duì)象序列化是對(duì)象永久化的一種機(jī)制。序列化通??梢宰詣?dòng)完成,但有時(shí)可能要對(duì)這個(gè)過程進(jìn)行控制。對(duì)于任何可能包含重要的安全性數(shù)據(jù)的對(duì)象,應(yīng)該使該對(duì)象不可序列化。如果它必須為可序列化的,也需要指定特定字段來保存不可序列化的重要數(shù)據(jù)。如果無法實(shí)現(xiàn)這一點(diǎn),則應(yīng)注意該數(shù)據(jù)會(huì)被公開給任何擁有序列化權(quán)限的代碼,并確保不讓任何惡意代碼獲得該權(quán)限。
Java在對(duì)類實(shí)現(xiàn)serializable接口時(shí),可通過關(guān)鍵字static或transient為類中的數(shù)據(jù)成員變量進(jìn)行定制,以實(shí)現(xiàn)保護(hù)特殊數(shù)據(jù)的目的。
將數(shù)據(jù)成員聲明為transient后,序列化過程就無法將其加進(jìn)對(duì)象字節(jié)流中,也就沒有從transient數(shù)據(jù)成員發(fā)送的數(shù)據(jù)。后面數(shù)據(jù)反序列化時(shí),要重建數(shù)據(jù)成員(因?yàn)樗穷惗x的一部分),但不包含任何數(shù)據(jù),因?yàn)檫@個(gè)數(shù)據(jù)成員不向流中寫入任何數(shù)據(jù)。
在本例的基礎(chǔ)上運(yùn)行例
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 學(xué)校2024-2025學(xué)年度德育工作計(jì)劃
- 進(jìn)行性肢端黑變病的臨床護(hù)理
- 【培訓(xùn)課件】銷售技能培訓(xùn) 顧問式實(shí)戰(zhàn)銷售
- 產(chǎn)后胳膊疼的健康宣教
- 低磷血癥的臨床護(hù)理
- 《教學(xué)管理》課件
- 變形桿菌性角膜炎的臨床護(hù)理
- JJF(陜) 077-2021 水泥膠砂試體成型振實(shí)臺(tái)校準(zhǔn)規(guī)范
- 幼兒教師培訓(xùn)課件:《信息交流》
- 創(chuàng)新教學(xué)方法提升幼兒園教育質(zhì)量計(jì)劃
- 俄語入門智慧樹知到期末考試答案章節(jié)答案2024年吉林師范大學(xué)
- 人教版七年級(jí)數(shù)學(xué)上冊(cè)第一學(xué)期期末綜合測(cè)試卷(2024年秋)
- 2023-2024學(xué)年吉林省長(zhǎng)春七年級(jí)(上)期末英語試卷
- 委托付款四方協(xié)議
- 2023年北京語言大學(xué)事業(yè)編制人員招聘考試真題
- 2024年03月國(guó)家林業(yè)和草原局機(jī)關(guān)服務(wù)局招考聘用筆試歷年典型考題及考點(diǎn)研判與答案解析
- 火龍罐療法課件
- 倉(cāng)庫(kù)租賃服務(wù)投標(biāo)方案(技術(shù)方案)
- 項(xiàng)目投資決策分析與評(píng)價(jià)(天大微專業(yè))智慧樹知到期末考試答案章節(jié)答案2024年
- 語言、文化與交際智慧樹知到期末考試答案章節(jié)答案2024年湖南大學(xué)
- 品三國(guó)論領(lǐng)導(dǎo)藝術(shù)智慧樹知到期末考試答案2024年
評(píng)論
0/150
提交評(píng)論