馬桶??Java 上廁所就能看完的小知識! 歡迎關(guān)注晤愧、點(diǎn)贊 持續(xù)更新大莫!
我們都知道,在學(xué)習(xí)對象序列化反序列化的時候都需要實(shí)現(xiàn)一個Serializable
接口
可是我們點(diǎn)進(jìn)去一看官份,這個接口長這個樣子
/
* @author unascribed
* @see java.io.ObjectOutputStream
* @see java.io.ObjectInputStream
* @see java.io.ObjectOutput
* @see java.io.ObjectInput
* @see java.io.Externalizable
* @since 1.1
*/
public interface Serializable {
}
沒錯 他是個空的只厘!
所以我們需要先搞清楚什么是序列化?
序列化的含義就是:序列化 (Serialization)是將對象的狀態(tài)信息轉(zhuǎn)換為可以存儲或傳輸?shù)男问降倪^程舅巷。
emmmm
說白了就是保存到硬盤或者其他地方進(jìn)行存儲一下羔味!
那我們不妨做個小東西實(shí)驗(yàn)一樣!爺天生傲骨钠右,就不實(shí)現(xiàn)又能怎么樣赋元?
先上代碼!
public class Person {
// private static final long serialVersionUID = 291613027204248679L;
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
private static void ObjectWriter() throws IOException {
FileOutputStream fos=new FileOutputStream("D:\\IO\\Person.object");
// 對象儲存文件的規(guī)范
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(new Person("Alien",21));
oos.close();
}
當(dāng)我們點(diǎn)擊運(yùn)行飒房!他報錯了搁凸!沒實(shí)現(xiàn)Serializable !
錯誤信息如下
Exception in thread "main" java.io.NotSerializableException: it.test.domain.Person
at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1185)
at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:349)
at it.test.domain.ObjectOutputStream_Test1.ObjectWriter(ObjectOutputStream_Test1.java:16)
at it.test.domain.ObjectOutputStream_Test1.main(ObjectOutputStream_Test1.java:7)
這個時候!我們就可以順騰摸瓜(查看報錯信息)狠毯!找到到底是哪里導(dǎo)致程序出現(xiàn)的異常护糖!
然后我們在ObjectOutputStream.java
文件中發(fā)現(xiàn)了以下代碼
節(jié)選:
if (obj instanceof String) {
writeString((String) obj, unshared);
} else if (cl.isArray()) {
writeArray(obj, desc, unshared);
} else if (obj instanceof Enum) {
writeEnum((Enum<?>) obj, desc, unshared);
} else if (obj instanceof Serializable) {
writeOrdinaryObject(obj, desc, unshared);
} else {
// 如果 都不符合 就會準(zhǔn)備報異常了!嚼松!
if (extendedDebugInfo) {
throw new NotSerializableException(
cl.getName() + "\n" + debugInfoStack.toString());
} else {
throw new NotSerializableException(cl.getName());
}
}
奧 嫡良! 他會將傳入的對象進(jìn)行判斷:是否是String
?是否是枚舉?是否是數(shù)組?是否實(shí)現(xiàn)Serializable
!
所以 對于源碼查看 我們知道了如果他實(shí)現(xiàn)了Serializable 那么才會被處理献酗! 這就是一種標(biāo)識 寝受!
如果他以上幾種情況 (string array...)都不是!那么就會報出異常了凌摄!
原來如此羡蛾!
所以這個東西:就是一種標(biāo)識 !
不會被序列化的可怕家族锨亏!
當(dāng)然痴怨!我們的設(shè)計(jì)師不能想著所有東西被序列化,那對象中有一些參數(shù)不想被序列化!(不器予!你不想@嗽濉)我們該怎么辦呢?
他們就是 static
和 transient
乾翔!
static
很好理解爱葵!這東西不歸對象管,當(dāng)你將屬性聲明成 static時反浓,它就投靠了類 萌丈。
你序列化ObjectStream
Object!!!
是對象 管我類的小弟(static)啥事?
所以被static修飾的就無法序列化了雷则!
transient
這東西就是java賦予你的神秘力量辆雾!畢竟我們不能把所有東西都設(shè)置成static,我們需要有屬于對象的 不被序列化月劈!
那么transient
就登場啦 如果你不想讓他即屬于對象又不會被序列化 那么你就給屬性添加該關(guān)鍵字!
private transient int age;
這個時候 就不會被序列化了 當(dāng)然每次反序列化都是默認(rèn)值了度迂!
但是理解歸理解!這東西在java里面代碼邏輯中到底是怎么實(shí)現(xiàn)的呢?
我們找到了ObjectStreamClass
中有如下代碼:
這個方法 上面注釋 我給大家翻譯下猜揪!
返回與給定類聲明的所有非靜態(tài)非瞬態(tài)字段相對應(yīng)的ObjectStreamFields
數(shù)組惭墓。
每個ObjectStreamField
都包含一個其代表的字段的Field對象。
如果沒有默認(rèn)的可序列化字段而姐,則返回NO_FIELDS
private static ObjectStreamField[] getDefaultSerialFields(Class<?> cl) {
// 獲取到序列化對象的參數(shù)數(shù)組
Field[] clFields = cl.getDeclaredFields();
ArrayList<ObjectStreamField> list = new ArrayList<>();
int mask = Modifier.STATIC | Modifier.TRANSIENT;
for (int i = 0; i < clFields.length; i++) {
//判斷是不是 非靜態(tài)非瞬態(tài)字段
// 添加所有 可序列化字段 進(jìn)入ArrayList<ObjectStreamField> 然后進(jìn)行后續(xù)操作
if ((clFields[i].getModifiers() & mask) == 0) {
list.add(new ObjectStreamField(clFields[i], false, true));
}
}
int size = list.size();
return (size == 0) ? NO_FIELDS :
list.toArray(new ObjectStreamField[size]);
}
沒錯 就是在這里判斷的腊凶!
當(dāng)然!Java序列化的本質(zhì)就是將Java對象轉(zhuǎn)化成字節(jié)數(shù)組來便于存儲和傳輸?shù)?br>
這就是Java序列化一步非常重要的過程啦拴念!
這里是??Java 每周不定時更新钧萍!喜歡的小伙伴可以點(diǎn)贊關(guān)注收藏哦!我們下個文章見丈莺!