從零開始的Minecraft - nbt序列化庫開發(fā):注解Ignore和InstanceAs

上一篇:從零開始的Minecraft - Nbt 序列化庫開發(fā):添加功能:LocateAt注解
項目地址:https://github.com/Cmyna/mnbt(可使用Jitpack配合Gradle/Maven導(dǎo)入項目)

摘要:簡單解釋了下兩個功能性注解InstanceAs和Ignore
前置知識:java,kotlin和其注解相關(guān)知識,對本項目其余內(nèi)容的了解
特別感謝:ChatGPT的文案

這兩個注解主要補充了兩個迫切需要的功能:當一個類的字段被聲明為一個接口時該如何處理,以及當我們不希望一個字段不被Mnbt序列化/反序列化時該如何處理。
InstanceAs注解(字面意思為”實例化為“)
注解負責(zé)處理字段對象,可以讓Mnbt不以字段聲明的類型來處理,而是以注解聲明的類型進行處理,例如:
如果不使用InstanceAs注解,那么Mnbt在處理該字段時只能知道這個字段是一個接口/抽象類,那么Mnbt便無法從創(chuàng)建一個該接口字段的實例,那么也就無法從Tag對象轉(zhuǎn)換成該字段需要的值。使用InstanceAs注解后就能通過字段注解獲取字段的實現(xiàn)類型,從而正常處理該字段。
實現(xiàn)該注解的功能也很簡單,負責(zé)處理反射轉(zhuǎn)換對象的ReflectiveConverter只需要判斷傳入的MTypeToken類型中的字段聲明是否帶有該注解,并根據(jù)注解聲明的類型處理字段轉(zhuǎn)換,而不是字段本身的類型聲明處理即可。唯一需要注意的只有下面2個問題:
注解聲明的類型必須是字段聲明類型的子類
注解聲明的類型不可為接口/抽象類
為處理這兩個問題,實際代碼實現(xiàn)如下:
Ignore注解:
用于指定是否忽略某個字段的 Ignore 注解。Ignore 注解可以指定在將對象轉(zhuǎn)換為 Tag 對象或?qū)?Tag對象 轉(zhuǎn)換為其他java對象時忽略特定的字段。該注解包括 ignoreToTag 和 ignoreFromTag 兩個布爾值參數(shù),用于指定是否忽略序列化或反序列化。代碼實現(xiàn)如下:
其中fieldValueProvider是一個實現(xiàn)了FieldValueProvider的類,參數(shù)用于指定在從Tag對象轉(zhuǎn)成java對象過程中,需要提供給該字段的值的來源。當一個字段被標記為 @IgnoreFromTag 時,該注解可以指定一個實現(xiàn)了 FieldValueProvider 接口的類,用于提供需要反序列化的字段的值。該接口只有一個方法 provide,用于返回指定字段的值。因此,fieldValueProvider 參數(shù)指定的類需要實現(xiàn)該接口并提供相應(yīng)的邏輯,以便在反序列化時正確地提供需要的字段值。需要注意的是,由于提供的是一個KClass(或javaClass)聲明,實際上該類的實例是由mnbt自行創(chuàng)建,而且要求該類必須提供一個空構(gòu)造器。FieldValueProvider的聲明如下:
因為每次使用Ingore注解都需要顯式指定其三個參數(shù),為了簡化注解使用,又實現(xiàn)了兩個注解:IgnoreFromTag和IgnoreToTag(也和參數(shù)同名)。如注解名字所示,IgnoreFromTag用于指定在從Tag對象轉(zhuǎn)成java對象時是否忽略該字段,因此需要FieldValueProvider實現(xiàn)類的參數(shù),而IgnoreToTag則不需要任何參數(shù),其所本身的含義就已經(jīng)代表了Ignore.ignoreToTag = true。
由于Ignore注解本身并不復(fù)雜,所以其在mnbt的實現(xiàn)也很簡單,也是在ReflectiveConverter中實現(xiàn)相應(yīng)功能,唯一需要注意的是其兩個子注解IgnoreFromTag和IgnoreToTag也要能發(fā)揮相應(yīng)的功能。我的做法是在得到Ignore注解后嘗試將其轉(zhuǎn)成IgnoreFromTag/IgnoreToTag注解對象,如果為空,那么說明Ignore注解對應(yīng)的參數(shù)為false。