一起养成写作习惯!这是我参与「日新计划 4 月更文挑战」的第2天,点击查看活动详情。
序列化
将实例的状态转换为可以存储或传输的形式的过程。
Objecandroid是什么手机牌子tOutputStream
构造函数
public ObjectOutputStream(OutputStream out) throws IOException {
verifySubclass();
bout = new BlockDataOutputStream(out);//用于写入文件的Stream
handles = new HandleTable(10, (float) 3.00);
subs = new ReplaceTable(10, (float) 3.00);
enableOverride = false;
writeStreamHeader(); //开始写入魔数和版本号
bout.setBlockDataMode(true);
if (extendedDebugInfo) {
debugInfoStack = new DebugTraceInfoStack();
} else {
debugInfoStack = null;
}
}
write二进制Object方法
public final void writeObject(Object obj) throws IOException {
if (enableOverride) {
writeObjectOverride(obj);
return;
}
try {
writeObject0(obj, false);
} catch (IOException ex) {
if (depth == 0) {
try {
writeFatalException(ex);
} catch (IOException ex2) {
}
}
throw ex;
}
}
调用writeObject0方法
private void writeObject0(Object obj, boolean unshared)
throws IOException
{
。。。
//创建出来一个原始数据的描述信息的实例
desc = ObjectStreamClass.lookup(cl, true);
。。。
//根据类型信息将实例信息写入输出流
if (obj instanceof Class) {
writeClass((Class) obj, unshared);
} else if (obj instanceof ObjectStreamClass) {
writeClassDesc((ObjectStreamClass) obj, unshared);
// END Android-changed: Make Class and ObjectStreamClass replaceable.
} else 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 {
if (extendedDebugInfo) {
throw new NotSerializableException(
cl.getName() + "n" + debugInfoStack.toString());
} else {
throw new NotSerializableException(cl.getName());
}
}
}
ObjectStreamClass的创建过程
static ObjectStreamClass lookup(Class<?> cl, boolean all) {
...
Reference<?> ref = Caches.localDescs.get(key);//读取缓存
Object entry = null;
if (ref != null) {
entry = ref.get();
}
EntryFuture future = null;
if (entry == null) {
EntryFuture newEntry = new EntryFuture();
Reference<?> newRef = new SoftReference<>(newEntry);
do {
if (ref != null) {
Caches.localDescs.remove(key, ref);
}
ref = Caches.localDescs.putIfAbsent(key, newRef);
if (ref != null) {
entry = ref.get();
}
} while (ref != null && entry == null);
if (entry == null) {
future = newEntry;
}
}
if (entry instanceof ObjectStreamClass) { // check common case first
return (ObjectStreamClass) entry;
}
if (entry instanceof EntryFuture) {
future = (EntryFuture) entry;
if (future.getOwner() == Thread.currentThread()) {
entry = null;
} else {
entry = future.get();
}
}
//没有缓存的情况
if (entry == null) {
try {
entry = new ObjectStreamClass(cl);
} catch (Throwable th) {
entry = th;
}
if (future.set(entry)) {
Caches.localDescs.put(key, new SoftReference<Object>(entry));
} else {
entry = future.get();
}
}
if (entry instanceof ObjectStreamClass) {
return (ObjectStreamClass) entry;
} else if (entry instanceof RuntimeException) {
throw (RuntimeException) entry;
} else if (entry instanceof Error) {
throw (Error) entry;
} else {
throw new InternalError("unexpected entry: " + entry);
}
}
进入ObjectStreamClass构造函数
private ObjectStreamClass(final Class<?> cl) {
this.cl = cl;
...
name = cl.getName();//反射获取
isProxy = Proxy.isProxyClass(cl);
isEnum = Enum.class.isAssignableFrom(cl);
serializable = Serializable.class.isAssignableFrom(cl);
externalizable = Externalizable.class.isAssignableFrom(cl);
Class<?> superCl = cl.getSuperclass();
superDesc = (superCl != null) ? lookup(superCl, false) : null;
...
suid = getDeclaredSUID(cl);
fields = getSerialFields(cl);
computeFieldOffsets();
initialized = true;
}
读取属性中使用反射
private static ObjectStreamField[] getDefaultSerialFields(Class<?> cl) {
Field[] clFields = cl.getDeclaredFields();
ArrayList<ObjectStreamField> list = new ArrayList<>();
int mask = Modifier.STATIC | Modifier.TRANSIENT;
for (int i = 0; i < clFields.length; i++) {
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]);
}
Parcelablkotlin面试题e
Kotlin 有一个Parceliz二进制亡者列车e注解可以帮我们生成实现Parcelable之后需要写的代码
- 对kotlin怎么读象自行实现出入口方法,避免对类结构的反射
- 二进制流存储在连续内存中,占用空间更小
- 牺牲易用性(可以通过Parcelize弥补),换取极致的性能
Serializable
- 用反射获取类的结构和属性信息,过程中会产生中间信息
- 有缓存结构,在解析相同类型的情况下,能复用缓存
- 性能在二进制转换器可接受的范围内,易用性比较好
Intent传值场景
进入Pjava模拟器arcel.java类中的writeSerializable
Serializable是先通过ObjectOutp二进制转化为十进制utStream,把对象转成ByteArray,再通过writeByteArray写入Parcel
public final void writeSerializable(@Nullable Serializable s) {
if (s == null) {
writeString(null);
return;
}
String name = s.getClass().getName();
writeString(name);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(s);
oos.close();
writeByteArray(baos.toByteArray());
} catch (IOException ioe) {
throw new RuntimeException("Parcelable encountered " +
"IOException writing serializable object (name = " + name +
")", ioe);
}
}
Parcelable 调用对象内部实现的writeToParcel方法中的逻辑,通过一些write方法直接写入Parcel
public static void writeToParcel(@Nullable CharSequence cs, @NonNull Parcel p,
int parcelableFlags) {
if (cs instanceof Spanned) {
p.writeInt(0);
p.writeString8(cs.toString());
Spanned sp = (Spanned) cs;
Object[] os = sp.getSpans(0, cs.length(), Object.class);
for (int i = 0; i < os.length; i++) {
Object o = os[i];
Object prop = os[i];
if (prop instanceof CharacterStyle) {
prop = ((CharacterStyle) prop).getUnderlying();
}
if (prop instanceof ParcelableSpan) {
final ParcelableSpan ps = (ParcelableSpan) prop;
final int spanTypeId = ps.getSpanTypeIdInternal();
if (spanTypeId < FIRST_SPAN || spanTypeId > LAST_SPAN) {
Log.e(TAG, "External class "" + ps.getClass().getSimpleName()
+ "" is attempting to use the frameworks-only ParcelableSpan"
+ " interface");
} else {
p.writeInt(spanTypeId);
ps.writeToParcelInternal(p, parcelableFlags);
writeWhere(p, sp, o);
}
}
}
p.writeInt(0);
} else {
p.writeInt(1);
if (cs != null) {
p.writeString8(cs.toString());
} else {
p.writeString8(null);
}
}
}
由于ObjectSt二进制计算器reamClass存在缓存机制,在一次序列化过程中,如果涉及大量相同类的不同实例化,Serializable的性能会存在优势。