JAVA基础4

您所在的位置:网站首页 java中对象序列化的含义和特点 JAVA基础4

JAVA基础4

2024-07-11 02:57| 来源: 网络整理| 查看: 265

一、什么是序列化和反序列化?

序列化:将对象状态信息转化成可以存储或传输的形式的过程(Java中就是将对象转化成字节序列的过程)

反序列化:从存储文件中恢复对象的过程(Java中就是通过字节序列转化成对象的过程)

 

二、为什么要序列化和反序列化?

Java中对象都是存储在内存中,准确地说是JVM的堆或栈内存中,可以各个线程之间进行对象传输,但是无法在进程之间进行传输。另外如果需要在网络传输中传输对象也没有办法,同样内存中的对象也没有办法直接保存成文件。

所以需要对对象进行序列化,序列化对象之后一个个的Java对象就变成了字节序列,而字节序列是可以传输和存储的。而反序列化就可以通过序列化生产的字节序列再恢复成序列化之前的对象状态及信息。

总结:

1、进程之间传输对象(如RPC、RMI通信)

2、网络通信时进行传输对象

3、持久化对象时需要将对象序列化

 

三、怎么序列化和反序列化?

实现序列化的方式有很多种,常用的方式有如下几种:

3.1、JDK序列化

JDK序列化时JDK自带的序列化方式,使用其他也比较方便,只需要序列化的类实现了Serializable接口即可,Serializable接口没有定义任何方法和属性,所以只是起到了标识的作用,表示这个类是可以被序列化的。

如果没有实现Serializable接口而进行序列化操作就会抛出NotSerializableException异常。

能够序列化的字段:属性变量、父类的属性变量(父类也需要实现Serializablie接口)

不能序列化的字段:静态变量、父类的属性变量、关键字transient修饰的变量、没有实现Serializable接口的对象属性

3.1.1、Serializable接口案例

定义类User、Person、Home、School分别如下

1 public class Home implements Serializable { 2 private String address; 3 4 public String getAddress() { 5 return address; 6 } 7 8 public void setAddress(String address) { 9 this.address = address; 10 } 11 } 1 public class School { 2 private String schoolName; 3 4 public String getSchoolName() { 5 return schoolName; 6 } 7 8 public void setSchoolName(String schoolName) { 9 this.schoolName = schoolName; 10 } 11 }

 

1 public class Person implements Serializable { 2 3 public static String parentType = "Person"; //父类静态变量 4 5 private String sex;//性别 6 7 public String getSex() { 8 return sex; 9 } 10 11 public void setSex(String sex) { 12 this.sex = sex; 13 } 14 }

 

public class User extends Person implements Serializable { public static boolean alive; //静态变量 private Long userId;//Long 类型 private int age; //int 类型 private String userName; //string 类型 private String password; //string 类型 private transient String IDCard; //不序列化的字段 private Date birth; //Date类型 private Home home; // 可以序列化的对象类型 private School school; //不可以序列化的对象类型 List friends; //List类型 /** set get 方法省略*/ }

 

案例中序列化的类为User,继承类Person,分别含有类Home和School的对象属性,序列化测试代码如下:

1 public class MainTest { 2 public static void main(String[] args) throws Exception{ 3 User user = new User(); 4 user.setAge(10); 5 user.setBirth(new Date()); 6 user.setPassword("123456"); 7 user.setUserName("Jack"); 8 user.setUserId(100L); 9 user.setSex("男"); 10 user.setIDCard("131313131313113"); 11 user.parentType = "son";//修改父类静态变量 12 user.alive = true; //修改User类的静态变量 13 14 Home home = new Home(); 15 home.setAddress("中国浙江"); 16 School school = new School(); 17 school.setSchoolName("清华大学"); 18 user.setHome(home);//设置对象属性 19 // user.setSchool(school);//设置对象属性 (因为School类没有实现Seriliazable接口,所以如果设置就会报错) 20 21 List friends = new ArrayList(); 22 User userF = new User(); 23 userF.setUserId(101L); 24 userF.setUserName("Friend"); 25 friends.add(userF); 26 user.setFriends(friends); 27 28 //序列化 29 serializer(user); 30 //反序列化 31 User newUser = derializer(); 32 //验证 33 System.out.println("验证两个对象是否相等"); 34 System.out.println("原对象地址:"+user.toString()); 35 System.out.println("新对象地址:"+newUser.toString()); 36 System.out.println("******************"); 37 System.out.println("打印两个对象"); 38 System.out.println("原对象数据:"+JSON.toJSON(user).toString()); 39 System.out.println("新对象数据:"+JSON.toJSON(newUser).toString()); 40 } 41 42 /**序列化对象*/ 43 private static void serializer(User user)throws Exception{ 44 ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(new File("/Users/xxw/testlog/user.txt"))); 45 outputStream.writeObject(user); 46 outputStream.close(); 47 } 48 49 /**反序列化对象*/ 50 private static User derializer()throws Exception{ 51 ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(new File("/Users/xxw/testlog/user.txt"))); 52 User user = (User) inputStream.readObject(); 53 inputStream.close(); 54 return user; 55 } 56 }

 

测试结果为:

1 验证两个对象是否相等 2 原对象地址:com.lucky.demo.base.seralizer.demo.User@3764951d 3 新对象地址:com.lucky.demo.base.seralizer.demo.User@4783da3f 4 ****************** 5 打印两个对象 6 原对象数据:{"iDCard":"131313131313113","password":"123456","sex":"男","birth":1573203467764,"userName":"Jack","userId":100,"age":10,"friends":[{"userName":"Friend","userId":101,"age":0}],"home":{"address":"中国浙江"}} 7 新对象数据:{"password":"123456","sex":"男","birth":1573203467764,"userName":"Jack","userId":100,"age":10,"friends":[{"userName":"Friend","userId":101,"age":0}],"home":{"address":"中国浙江"}}

 

这里User类的School属性没有实现Serializable接口,所以如果给school属性赋值然后进行序列化就会报错,结果如下:

1 Exception in thread "main" java.io.NotSerializableException: com.lucky.demo.base.seralizer.demo.School 2 at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184) 3 at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548) 4 at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509) 5 at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432) 6 at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178) 7 at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348) 8 at com.lucky.demo.base.seralizer.demo.MainTest.serializer(MainTest.java:59) 9 at com.lucky.demo.base.seralizer.demo.MainTest.main(MainTest.java:43)

 

而如果User类的父类Person没有实现Serializable接口,那么序列化的时候不会报错,但是父类中的属性在反序列化之后字段就会没有,结果如下:

1 打印两个对象 2 原对象数据:{"iDCard":"131313131313113","password":"123456","sex":"男","birth":1573203839905,"userName":"Jack","userId":100,"age":10,"friends":[{"userName":"Friend","userId":101,"age":0}],"home":{"address":"中国浙江"}} 3 新对象数据:{"password":"123456","birth":1573203839905,"userName":"Jack","userId":100,"age":10,"friends":[{"userName":"Friend","userId":101,"age":0}],"home":{"address":"中国浙江"}}

 

这里就没有了父类的属性sex字段

 

3.1.2、Serializable接口实现原理

Serializable接口是一个空接口,没有定义任何的方法和属性,所以Serialiazable接口的作用就是起到一个标识的作用,源码如下

1 public interface Serializable { 2 }

 

Serializable接口既然是标识的作用,那么就需要在实际序列化操作的时候进行识别,而实际的序列化操作是通过ObjectOutputStream 和 ObjectInputStream实现的,那么接下来就看下这两个类的是如何实现序列化和反序列化的

3.1.2.1、ObjectOutputStream源码解析

构造函数如下

1 public ObjectOutputStream(OutputStream out) throws IOException { 2 verifySubclass(); 3 bout = new BlockDataOutputStream(out); 4 handles = new HandleTable(10, (float) 3.00); 5 subs = new ReplaceTable(10, (float) 3.00); 6 enableOverride = false; 7 writeStreamHeader(); 8 bout.setBlockDataMode(true); 9 if (extendedDebugInfo) { 10 debugInfoStack = new DebugTraceInfoStack(); 11 } else { 12 debugInfoStack = null; 13 } 14 }

 

OutoutStream表示保存的二进制流,也就是将序列化的对象保存到这个二进制流中,再看下具体的序列化方法源码如下:

1 public final void writeObject(Object obj) throws IOException { 2 if (enableOverride) {//enableOverride 表示是否可以被覆盖,默认为false 3 writeObjectOverride(obj); 4 return; 5 } 6 try { 7 //执行具体的序列化操作 8 writeObject0(obj, false); 9 } catch (IOException ex) { 10 if (depth == 0) { 11 writeFatalException(ex); 12 } 13 throw ex; 14 } 15 }

 

 最终执行了writeObject0(obj, false)方法,代码如下:

1 private void writeObject0(Object obj, boolean unshared) 2 throws IOException 3 { 4 boolean oldMode = bout.setBlockDataMode(false); 5 depth++; 6 try { 7 // handle previously written and non-replaceable objects 8 // 处理已经处理过的和不可替换的对象,这些是不可序列化的 9 int h; 10 if ((obj = subs.lookup(obj)) == null) { 11 writeNull(); 12 return; 13 } else if (!unshared && (h = handles.lookup(obj)) != -1) { 14 writeHandle(h); 15 return; 16 } else if (obj instanceof Class) { 17 writeClass((Class) obj, unshared); 18 return; 19 } else if (obj instanceof ObjectStreamClass) { 20 writeClassDesc((ObjectStreamClass) obj, unshared); 21 return; 22 } 23 24 // check for replacement object 25 Object orig = obj; 26 //获取对象的Class对象 27 Class cl = obj.getClass(); 28 ObjectStreamClass desc; 29 for (;;) { 30 // REMIND: skip this check for strings/arrays? 31 Class repCl; 32 //获取Class的描述信息,并且判断是否是Serializable接口 33 desc = ObjectStreamClass.lookup(cl, true); 34 if (!desc.hasWriteReplaceMethod() || 35 (obj = desc.invokeWriteReplace(obj)) == null || 36 (repCl = obj.getClass()) == cl) 37 { 38 break; 39 } 40 cl = repCl; 41 } 42 43 //如果允许被替换的情况 44 if (enableReplace) { 45 Object rep = replaceObject(obj); 46 if (rep != obj && rep != null) { 47 cl = rep.getClass(); 48 desc = ObjectStreamClass.lookup(cl, true); 49 } 50 obj = rep; 51 } 52 53 // if object replaced, run through original checks a second time 54 // 如果对象被替换了,只有是ObjectOutputStream的子类才会出现 55 if (obj != orig) { 56 subs.assign(orig, obj); 57 if (obj == null) { 58 writeNull(); 59 return; 60 } else if (!unshared && (h = handles.lookup(obj)) != -1) { 61 writeHandle(h); 62 return; 63 } else if (obj instanceof Class) { 64 writeClass((Class) obj, unshared); 65 return; 66 } else if (obj instanceof ObjectStreamClass) { 67 writeClassDesc((ObjectStreamClass) obj, unshared); 68 return; 69 } 70 } 71 72 // remaining cases 73 /**序列化不同类型的对象,分别序列化String、数组、枚举类型 74 * 对于Integer、Long等都属于实现了Serializable接口的数据类型*/ 75 if (obj instanceof String) {//序列化字符串类型对象 76 writeString((String) obj, unshared); 77 } else if (cl.isArray()) {//序列化数组类型对象 78 writeArray(obj, desc, unshared); 79 } else if (obj instanceof Enum) {//序列化枚举类型对象 80 writeEnum((Enum) obj, desc, unshared); 81 } else if (obj instanceof Serializable) {//序列化实现了Serializable接口的数据类型 82 writeOrdinaryObject(obj, desc, unshared); 83 } else {//抛出不可序列化异常 84 if (extendedDebugInfo) { 85 throw new NotSerializableException( 86 cl.getName() + "\n" + debugInfoStack.toString()); 87 } else { 88 throw new NotSerializableException(cl.getName()); 89 } 90 } 91 } finally { 92 depth--; 93 bout.setBlockDataMode(oldMode); 94 } 95 } 96 }

 

前面都是在做各种检查,实际有效的代码就是从75行开始,分别针对不同类型的对象分别执行不同的序列化方法

writeString方法的逻辑就是将字符串按字节的方式进行序列化,底层就是通过数组复制的方式获取到char[],然后写入到缓存的序列化的byte[]数组中

1 System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);

 writeArray方法的逻辑就是先判断数组的数据类型是什么,如果是基本数据类型之间写入byte数字,如果是对象类型就调用writeObject0方法

writeEnum方法的逻辑是直接写入枚举的值

而对于对象类型是比较复杂的,也就是writeOrdinaryObject方法,逻辑如下:

1 private void writeOrdinaryObject(Object obj, 2 ObjectStreamClass desc, 3 boolean unshared) 4 throws IOException 5 { 6 if (extendedDebugInfo) { 7 debugInfoStack.push( 8 (depth == 1 ? "root " : "") + "object (class \"" + 9 obj.getClass().getName() + "\", " + obj.toString() + ")"); 10 } 11 try { 12 //检查ObjectStreamClass对象 13 desc.checkSerialize(); 14 15 //写入标记表示是Object类型 16 bout.writeByte(TC_OBJECT); 17 //写入Class对象的描述信息 18 writeClassDesc(desc, false); 19 handles.assign(unshared ? null : obj); 20 if (desc.isExternalizable() && !desc.isProxy()) { 21 //写入实现了Externalizable接口的对象 22 writeExternalData((Externalizable) obj); 23 } else { 24 //写入实现了Serializable 25 writeSerialData(obj, desc); 26 } 27 } finally { 28 if (extendedDebugInfo) { 29 debugInfoStack.pop(); 30 } 31 } 32 }

 最终按实现了Externalizable接口或Serializable接口分别执行writeExternalData和writeSerialData方法,writeSerialData方法如下:

1 private void writeSerialData(Object obj, ObjectStreamClass desc) 2 throws IOException 3 { 4 //获取类的描述信息对象 5 ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout(); 6 for (int i = 0; i < slots.length; i++) { 7 ObjectStreamClass slotDesc = slots[i].desc; 8 //判断该类是否自定义类writeObject方法,如果重写了该方法则按重写的逻辑处理 9 if (slotDesc.hasWriteObjectMethod()) { 10 ObjectOutputStream.PutFieldImpl oldPut = curPut; 11 curPut = null; 12 SerialCallbackContext oldContext = curContext; 13 14 if (extendedDebugInfo) { 15 debugInfoStack.push( 16 "custom writeObject data (class \"" + 17 slotDesc.getName() + "\")"); 18 } 19 try { 20 curContext = new SerialCallbackContext(obj, slotDesc); 21 bout.setBlockDataMode(true); 22 //通过反射的方式执行自定义的writeObejct方法 23 slotDesc.invokeWriteObject(obj, this); 24 bout.setBlockDataMode(false); 25 bout.writeByte(TC_ENDBLOCKDATA); 26 } finally { 27 curContext.setUsed(); 28 curContext = oldContext; 29 if (extendedDebugInfo) { 30 debugInfoStack.pop(); 31 } 32 } 33 34 curPut = oldPut; 35 } else { 36 //如果没有自定义writeObject方法则按默认的方法写入属性数据 37 defaultWriteFields(obj, slotDesc); 38 } 39 } 40 }

 

先是根据类的描述信息判断是否自定义了序列化方法writeObejct方法,如果自定义了就通过反射执行invokeWriteObejct方法,如果没有自定义则执行defaultWriteFields方法,defaultWriteFields方法逻辑如下:

 

1 private void defaultWriteFields(Object obj, ObjectStreamClass desc) 2 throws IOException 3 { 4 Class cl = desc.forClass(); 5 //校验对象的类信息是否和类描述信息一致 6 if (cl != null && obj != null && !cl.isInstance(obj)) { 7 throw new ClassCastException(); 8 } 9 10 // 11 desc.checkDefaultSerialize(); 12 13 int primDataSize = desc.getPrimDataSize(); 14 if (primVals == null || primVals.length 0) { 6 throw new OptionalDataException(remain); 7 } else if (defaultDataEnd) { 8 /* 9 * Fix for 4360508: stream is currently at the end of a field 10 * value block written via default serialization; since there 11 * is no terminating TC_ENDBLOCKDATA tag, simulate 12 * end-of-custom-data behavior explicitly. 13 */ 14 throw new OptionalDataException(true); 15 } 16 bin.setBlockDataMode(false); 17 } 18 19 byte tc; 20 //从流中读取int数据,序列化时候写入的时候写入属性之前都会写入int值表示属性的类型 21 while ((tc = bin.peekByte()) == TC_RESET) { 22 bin.readByte(); 23 handleReset(); 24 } 25 26 depth++; 27 totalObjectRefs++; 28 try { 29 /**判断读取的int数据表示当前读取的是什么类型的数据结构 30 * 不同的类型数据分别执行不同的解析方法*/ 31 switch (tc) { 32 case TC_NULL: 33 return readNull(); 34 35 case TC_REFERENCE: 36 return readHandle(unshared); 37 38 case TC_CLASS: 39 return readClass(unshared); 40 41 case TC_CLASSDESC: 42 case TC_PROXYCLASSDESC: 43 return readClassDesc(unshared); 44 45 case TC_STRING: 46 case TC_LONGSTRING: 47 return checkResolve(readString(unshared)); 48 49 case TC_ARRAY: 50 return checkResolve(readArray(unshared)); 51 52 case TC_ENUM: 53 return checkResolve(readEnum(unshared)); 54 55 case TC_OBJECT: 56 return checkResolve(readOrdinaryObject(unshared)); 57 58 case TC_EXCEPTION: 59 IOException ex = readFatalException(); 60 throw new WriteAbortedException("writing aborted", ex); 61 62 case TC_BLOCKDATA: 63 case TC_BLOCKDATALONG: 64 if (oldMode) { 65 bin.setBlockDataMode(true); 66 bin.peek(); // force header read 67 throw new OptionalDataException( 68 bin.currentBlockRemaining()); 69 } else { 70 throw new StreamCorruptedException( 71 "unexpected block data"); 72 } 73 74 case TC_ENDBLOCKDATA: 75 if (oldMode) { 76 throw new OptionalDataException(true); 77 } else { 78 throw new StreamCorruptedException( 79 "unexpected end of block data"); 80 } 81 82 default: 83 throw new StreamCorruptedException( 84 String.format("invalid type code: %02X", tc)); 85 } 86 } finally { 87 depth--; 88 bin.setBlockDataMode(oldMode); 89 } 90 }

 

1 private Object checkResolve(Object obj) throws IOException { 2 if (!enableResolve || handles.lookupException(passHandle) != null) { 3 return obj; 4 } 5 Object rep = resolveObject(obj); 6 if (rep != obj) { 7 // The type of the original object has been filtered but resolveObject 8 // may have replaced it; filter the replacement's type 9 if (rep != null) { 10 if (rep.getClass().isArray()) { 11 filterCheck(rep.getClass(), Array.getLength(rep)); 12 } else { 13 filterCheck(rep.getClass(), -1); 14 } 15 } 16 handles.setObject(passHandle, rep); 17 } 18 return rep; 19 }

 

解析的方法分别是readString()、readArray()、readEnum()、readOrdinaryObject()方法

解析字符串的方法就是直接从流中读取字节,解析数组和枚举的过程差不多,重点是解析对象的逻辑,代码如下:

1 private Object readOrdinaryObject(boolean unshared) 2 throws IOException 3 { 4 //判断是否是对象类型 5 if (bin.readByte() != TC_OBJECT) { 6 throw new InternalError(); 7 } 8 9 //读取类描述信息对象 10 ObjectStreamClass desc = readClassDesc(false); 11 desc.checkDeserialize(); 12 13 Class cl = desc.forClass(); 14 if (cl == String.class || cl == Class.class 15 || cl == ObjectStreamClass.class) { 16 throw new InvalidClassException("invalid class descriptor"); 17 } 18 19 Object obj; 20 try { 21 /** 22 * isInstantiable方法是判断是否有public的无参构造方法表示是否可以初始化对象 23 * 然后通过Constructor的newInstance方法初始化对象 24 * */ 25 //通过反射执行Class的newInstance方法构造对象 26 obj = desc.isInstantiable() ? desc.newInstance() : null; 27 } catch (Exception ex) { 28 throw (IOException) new InvalidClassException( 29 desc.forClass().getName(), 30 "unable to create instance").initCause(ex); 31 } 32 33 passHandle = handles.assign(unshared ? unsharedMarker : obj); 34 ClassNotFoundException resolveEx = desc.getResolveException(); 35 if (resolveEx != null) { 36 handles.markException(passHandle, resolveEx); 37 } 38 39 if (desc.isExternalizable()) { 40 //反序列化实现了Externalizable接口的对象 41 readExternalData((Externalizable) obj, desc); 42 } else { 43 //反序列化实现了Serializable接口的对象 44 readSerialData(obj, desc); 45 } 46 47 handles.finish(passHandle); 48 49 if (obj != null && 50 handles.lookupException(passHandle) == null && 51 desc.hasReadResolveMethod()) 52 { 53 Object rep = desc.invokeReadResolve(obj); 54 if (unshared && rep.getClass().isArray()) { 55 rep = cloneArray(rep); 56 } 57 if (rep != obj) { 58 // Filter the replacement object 59 if (rep != null) { 60 if (rep.getClass().isArray()) { 61 filterCheck(rep.getClass(), Array.getLength(rep)); 62 } else { 63 filterCheck(rep.getClass(), -1); 64 } 65 } 66 handles.setObject(passHandle, obj = rep); 67 } 68 } 69 70 return obj; 71 }

 

和序列化的时候一样,先判断是实现了Externalizable接口还是Serializable接口分别执行不同的逻辑,readSerialData方法逻辑如下:

1 private void readSerialData(Object obj, ObjectStreamClass desc) 2 throws IOException 3 { 4 ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout(); 5 for (int i = 0; i < slots.length; i++) {//遍历类描述信息 6 ObjectStreamClass slotDesc = slots[i].desc; 7 if (slots[i].hasData) { 8 if (obj == null || handles.lookupException(passHandle) != null) { 9 defaultReadFields(null, slotDesc); //没有数据可以解析 10 } else if (slotDesc.hasReadObjectMethod()) {//如果有自定义的readObejct方法则按自定义的逻辑执行 11 ThreadDeath t = null; 12 boolean reset = false; 13 SerialCallbackContext oldContext = curContext; 14 if (oldContext != null) 15 oldContext.check(); 16 try { 17 curContext = new SerialCallbackContext(obj, slotDesc); 18 19 bin.setBlockDataMode(true); 20 slotDesc.invokeReadObject(obj, this); 21 } catch (ClassNotFoundException ex) { 22 /* 23 * In most cases, the handle table has already 24 * propagated a CNFException to passHandle at this 25 * point; this mark call is included to address cases 26 * where the custom readObject method has cons'ed and 27 * thrown a new CNFException of its own. 28 */ 29 handles.markException(passHandle, ex); 30 } finally { 31 do { 32 try { 33 curContext.setUsed(); 34 if (oldContext!= null) 35 oldContext.check(); 36 curContext = oldContext; 37 reset = true; 38 } catch (ThreadDeath x) { 39 t = x; // defer until reset is true 40 } 41 } while (!reset); 42 if (t != null) 43 throw t; 44 } 45 46 /* 47 * defaultDataEnd may have been set indirectly by custom 48 * readObject() method when calling defaultReadObject() or 49 * readFields(); clear it to restore normal read behavior. 50 */ 51 defaultDataEnd = false; 52 } else { 53 //没有自定义的readObject方法则按默认的解析方法进行解析 54 defaultReadFields(obj, slotDesc); 55 } 56 57 if (slotDesc.hasWriteObjectData()) { 58 skipCustomData(); 59 } else { 60 bin.setBlockDataMode(false); 61 } 62 } else { 63 if (obj != null && 64 slotDesc.hasReadObjectNoDataMethod() && 65 handles.lookupException(passHandle) == null) 66 { 67 slotDesc.invokeReadObjectNoData(obj); 68 } 69 } 70 } 71 } 

这里也是先判断是否自定义了反序列化的方法readObject,如果有就按自定义的执行,如果没有就执行默认的反序列化方法defaultReadFields方法执行

1 private void defaultReadFields(Object obj, ObjectStreamClass desc) 2 throws IOException 3 { 4 Class cl = desc.forClass(); 5 if (cl != null && obj != null && !cl.isInstance(obj)) { 6 throw new ClassCastException(); 7 } 8 9 int primDataSize = desc.getPrimDataSize(); 10 if (primVals == null || primVals.length


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3