$30 off During Our Annual Pro Sale. View Details »

Android Parcelable vs Serializable. Что лучше?

Android Parcelable vs Serializable. Что лучше?

Видеозапись доклада https://youtu.be/tko54cjc79U

Разбор способов сериализации на Android и чем отличаются Parcelable и Serializable, а самое главное что лучше и быстрее

Эксперт - Павел Борзиков, Android разработчик в Avito
Начал свою карьеру разработчика в 2014 году в Краснодарском стартапе. Успел набраться опыта в разработке банковского приложения, сервисе доставки еды, а сейчас делает лучше жизнь пользователям Авито.

🔗 Подпишись на канал https://www.youtube.com/channel/UCKsqMPIIhev3qbMxCL8Emvw/join
🔗 Telegram канал "Android Broadcast" https://ttttt.me/android_broadcast

Android Broadcast

October 17, 2021
Tweet

More Decks by Android Broadcast

Other Decks in Programming

Transcript

  1. Павел Борзиков Android Developer Serializable Parcelable VS Москва — 2021

  2. 2 ТЕРМИНОЛОГИЯ Person Name John Surname Smith Age 21 1

    0 1 1 1 1 0 1 0 1 1 0 1 1 0 0 1 0 0 1 0 1 0 0 1 1 1 Сериализация Процесс перевода структуры данных в последовательность байтов.
  3. 3 ТЕРМИНОЛОГИЯ Person Name John Surname Smith Age 21 1

    0 1 1 1 1 0 1 0 1 1 0 1 1 0 0 1 0 0 1 0 1 0 0 1 1 1 Десериализация Создание структуры данных из битовой последовательности.
  4. 4 ПРИМЕР КЛАССА package com.myapplication class Person( private val name:

    String, private val surname: String, private val age: Int, )
  5. 5 ИНТЕРФЕЙС В JAVA package java.io; public interface Serializable {

    }
  6. 6 СТРУКТУРА КЛАССА И ДАННЫЕ package com.myapplication class Person( private

    val name: String, private val surname: String, private val age: Int, ) : Serializable
  7. 7 ПРИМЕР СЕРИАЛИЗАЦИИ val serializablePerson = Person( name = "John",

    surname = "Smith", age = 21, ) val filePath = "${directory}/serialized.bin" val file = File(filePath).apply { createNewFile() } // write Person val fileOutputStream = FileOutputStream(file) ObjectOutputStream(fileOutputStream).use { it.writeObject(serializablePerson) it.flush() } // read Person val fileInputStream = FileInputStream(file) ObjectInputStream(fileInputStream).use { print(it.readObject() as Person) }
  8. 8 ПРИМЕР СЕРИАЛИЗАЦИИ val serializablePerson = Person( name = "John",

    surname = "Smith", age = 21, ) val filePath = "${directory}/serialized.bin" val file = File(filePath).apply { createNewFile() } // write Person val fileOutputStream = FileOutputStream(file) ObjectOutputStream(fileOutputStream).use { it.writeObject(serializablePerson) it.flush() }
  9. 9 ПРИМЕР СЕРИАЛИЗАЦИИ val serializablePerson = Person( name = "John",

    surname = "Smith", age = 21, ) val filePath = "${directory}/serialized.bin" val file = File(filePath).apply { createNewFile() } // read Person val fileInputStream = FileInputStream(file) ObjectInputStream(fileInputStream).use { print(it.readObject() as Person) }
  10. 10 ПРИМЕР СЕРИАЛИЗАЦИИ val serializablePerson = Person( name = "John",

    surname = "Smith", age = 21, ) val filePath = "${directory}/serialized.bin" val file = File(filePath).apply { createNewFile() } /
  11. 11 Содержимое serialized.bin АНАЛИЗ СЕРИАЛИЗОВАННЫХ ДАННЫХ ?? sr*com.myapplication.Person ?? T»1?

    IageLnametLjava/lang/String;L surnameq~xptJohntSmith
  12. 12 Пакеты класса и переменных; 01. Содержимое serialized.bin АНАЛИЗ СЕРИАЛИЗОВАННЫХ

    ДАННЫХ ?
  13. 13 Пакеты класса и переменных; 01. Содержимое serialized.bin Имена переменных;

    02. АНАЛИЗ СЕРИАЛИЗОВАННЫХ ДАННЫХ ?
  14. 14 Значения. Пакеты класса и переменных; 01. Содержимое serialized.bin Имена

    переменных; 02. 03. АНАЛИЗ СЕРИАЛИЗОВАННЫХ ДАННЫХ ?
  15. 15 Значения. Пакеты класса и переменных; 01. Содержимое serialized.bin Имена

    переменных; 02. 03. АНАЛИЗ СЕРИАЛИЗОВАННЫХ ДАННЫХ ?? sr*com.myapplication.Person ?? T»1? IageLnametLjava/lang/String;L surnameq~xptJohntSmith
  16. 16 Механизм исследования данных о программе во время ее выполнения.

    REFLECTION API
  17. 17 ПРИМЕР РЕФЛЕКСИИ val person = Person( name = "John",

    surname = "Smith", age = 21, ) val clazz: Class<Person> = person.javaClass val field: Field = clazz.getDeclaredField("name") field.isAccessible = true println(field.get(person)) println(field.type) println(field.declaringClass)
  18. 18 ПРИМЕР РЕФЛЕКСИИ val person = Person( name = "John",

    surname = "Smith", age = 21, ) val clazz: Class<Person> = person.javaClass val field: Field = clazz.getDeclaredField("name") field.isAccessible = true println(field.get(person)) println(field.type) println(field.declaringClass) val clazz: Class<Person> = person.javaClass
  19. 19 ПРИМЕР РЕФЛЕКСИИ val person = Person( name = "John",

    surname = "Smith", age = 21, ) val clazz: Class<Person> = person.javaClass val field: Field = clazz.getDeclaredField("name") field.isAccessible = true println(field.get(person)) println(field.type) println(field.declaringClass) val field: Field = clazz.getDeclaredField("name")
  20. 20 ПРИМЕР РЕФЛЕКСИИ val person = Person( name = "John",

    surname = "Smith", age = 21, ) val clazz: Class<Person> = person.javaClass val field: Field = clazz.getDeclaredField("name") field.isAccessible = true println(field.get(person)) println(field.type) println(field.declaringClass) println(field.get(person)) println(field.type) println(field.declaringClass) Stdout: John class java.lang.String class com.myapplication.Person
  21. 21 ПРОБЛЕМА РЕФЛЕКСИИ НА ANDROID

  22. 22 01. ПРОБЛЕМА РЕФЛЕКСИИ НА ANDROID Рефлексия медленная. Чтобы обратится

    к объектам, сначала надо их «исследовать»;
  23. 23 01. Потребление памяти. Во время «исследования» создаются дополнительные объекты;

    02. ПРОБЛЕМА РЕФЛЕКСИИ НА ANDROID Рефлексия медленная. Чтобы обратится к объектам, сначала надо их «исследовать»;
  24. 24 01. Потребление памяти. Во время «исследования» создаются дополнительные объекты;

    02. Частый вызов GC. Следствие большого потребления памяти; 03. ПРОБЛЕМА РЕФЛЕКСИИ НА ANDROID Рефлексия медленная. Чтобы обратится к объектам, сначала надо их «исследовать»;
  25. 25 01. Потребление памяти. Во время «исследования» создаются дополнительные объекты;

    02. Частый вызов GC. Следствие большого потребления памяти; 03. Слабое железо. Непростая задача для первых Android смартфонов. 04. ПРОБЛЕМА РЕФЛЕКСИИ НА ANDROID Рефлексия медленная. Чтобы обратится к объектам, сначала надо их «исследовать»;
  26. 26 01. Потребление памяти. Во время «исследования» создаются дополнительные объекты;

    02. Частый вызов GC. Следствие большого потребления памяти; 03. Слабое железо. Непростая задача для первых Android смартфонов. 04. ПРОБЛЕМА РЕФЛЕКСИИ НА ANDROID Рефлексия медленная. Чтобы обратится к объектам, сначала надо их «исследовать»; И СЕРИАЛИЗАЦИИ
  27. 27 Parcel (с англ.) - посылка, сверток. PARCELABLE СОБСТВННОЕ ОПТИМАЛЬНОЕ

    РЕШЕНИЕ В ANDROID
  28. 28 ПРИМЕР PARCELABLE class Person( ... ) : Parcelable {

    override fun describeContents() = 0 override fun writeToParcel(dest:Parcel,flags:Int) { dest.writeString(name) dest.writeString(surname) dest.writeInt(age) } companion object CREATOR : Creator<Person> { override fun createFromParcel(parcel: Parcel) = Person( name = parcel.readString() ! ! , surname = parcel.readString() !! , age = parcel.readInt(), ) override fun newArray(size: Int) = ... } }
  29. 29 ПРИМЕР PARCELABLE class Person( .

  30. 30 ПРИМЕР PARCELABLE class Person( ! ! , surname =

    parcel.readString() !! , age = parcel.readInt(), )
  31. 31 ПРИМЕР PARCELABLE class Person( ! ! , surname =

    parcel.readString() !! , age = parcel.readInt(),
  32. 32 ЗАПИСЬ В PARCEL Parcel

  33. 33 ЗАПИСЬ В PARCEL Parcel John

  34. 34 ЗАПИСЬ В PARCEL Parcel John Smith

  35. 35 ЗАПИСЬ В PARCEL Parcel John Smith 21

  36. 36 ЧТЕНИЕ ИЗ PARCEL Parcel John Smith 21

  37. 37 ЧТЕНИЕ ИЗ PARCEL Parcel John Smith 21

  38. 38 ЧТЕНИЕ ИЗ PARCEL Parcel John Smith 21

  39. 39 ЧТЕНИЕ ИЗ PARCEL Parcel John Smith 21

  40. 40 ПРИМЕР PARCELABLE class Person( ... ) : Parcelable {

    override fun describeContents() = 0 override fun writeToParcel(dest:Parcel,flags:Int) { dest.writeString(name) dest.writeString(surname) dest.writeInt(age) } companion object CREATOR : Creator<Person> { override fun createFromParcel(parcel: Parcel) = Person( parcel.readString() !! , parcel.readString() !! , parcel.readInt(), ) override fun newArray(size: Int) = ... } }
  41. 41 ПОЛУЧЕНИЕ БАЙТОВ ИЗ PARCEL val person = Person( name

    = "John", secondName = "Smith", age = 21, ) val source = Parcel.obtain() source.writeParcelable(person, 0) val bytes = source.marshall() parcelSource.recycle() val destination = Parcel.obtain() destination.unmarshall(bytes, 0, bytes.size) destination.setDataPosition(0) val classLoader = Person : : class.java.classLoader val result = destination.readParcelable(classLoader) parcelDestination.recycle() println(result)
  42. 42 ПОЛУЧЕНИЕ БАЙТОВ ИЗ PARCEL val person = Person( name

    = "John", secondName = "Smith", age = 21, ) val source = Parcel.obtain() source.writeParcelable(person, 0) val bytes = source.marshall() parcelSource.recycle() val destination = Parcel.obtain() destination.unmarshall(bytes, 0, bytes.size) destination.setDataPosition(0) val classLoader = Person :
  43. 43 ПОЛУЧЕНИЕ БАЙТОВ ИЗ PARCEL val person = Person( name

    = "John", secondName = "Smith", age = 21, ) val source = Parcel.obtain() source.writeParcelable(person, 0) val bytes = source.marshall() parcelSource.recycle() val destination = Parcel.obtain() destination.unmarshall(bytes, 0, bytes.size) destination.setDataPosition(0) val classLoader = Person : : class.java.classLoader val result = destination.readParcelable(classLoader) println(result)
  44. 44 БАЙТЫ В СТРОКУ □≣≣≣c≣o≣m≣.≣m≣y≣a≣p≣p≣l≣i≣c≣a≣t≣i≣o≣n≣.≣P≣e≣r≣ s≣o≣n≣≣≣≣≣□≣≣≣J≣o≣h≣n≣≣≣≣≣□≣≣≣S≣m≣i≣t≣h≣≣≣□≣≣≣ String(bytes, StandartCharsets.UTF_8)

  45. 45 ПОЛУЧЕНИЕ БАЙТОВ ИЗ PARCEL val person = Person( name

    = "John", secondName = "Smith", age = 21, ) val source = Parcel.obtain() source.writeParcelable(person, 0) val bytes = source.marshall() parcelSource.recycle() val destination = Parcel.obtain() destination.unmarshall(bytes, 0, bytes.size) destination.setDataPosition(0) val classLoader = Person :
  46. 46 ДОКУМЕНТАЦИЯ The data you retrieve here must not be

    placed in any kind of persistent storage (on local disk, across a network, etc). For that, you should use standard serialization or another kind of general serialization mechanism. The Parcel marshalled representation is highly optimized for local IPC, and as such does not attempt to maintain compatibility with data created in different versions of the platform. Parcel.marshall()
  47. 47 ПРОВЕРКА ОПТИМИЗАЦИЙ В лабораторных условиях

  48. 48 val person = Person( name = "John", secondName =

    "Smith", age = 21, ) val source = Parcel.obtain() source.writeParcelable(person, 0) val bytes = source.marshall() parcelSource.recycle() val destination = Parcel.obtain() destination.unmarshall(sourceBytes, 0, bytes.size) destination.setDataPosition(0) val classLoader = Person : : class.java.classLoader val result = destination.readParcelable(classLoader) parcelDestination.recycle() println(result) КАК ЗАМЕРЯЕМ PARCELABLE
  49. 49 КАК ЗАМЕРЯЕМ SERIALIZABLE val serializablePerson = Person( name =

    "John", surname = "Smith", age = 21, ) val outputStream = ByteArrayOutputStream(120) // write Person ObjectOutputStream(outputStream).use { it.writeObject(serializablePerson) it.flush() } // read Person val fileInputStream = FileInputStream(outputStream) ObjectInputStream(fileInputStream).use { print(it.readObject() as Person) }
  50. 50 КАК ЗАМЕРЯЕМ Среднее время работы с 10 запусков;

  51. 51 Устройства: ▶ Pixel 4 ( API 29 ); 


    ▶ Samsung A300F ( API 21 ). КАК ЗАМЕРЯЕМ Среднее время работы с 10 запусков;
  52. 52 Устройства: ▶ Pixel 4 ( API 29 ); 


    ▶ Samsung A300F ( API 21 ). Размер полученного массива байт. КАК ЗАМЕРЯЕМ Среднее время работы с 10 запусков;
  53. 53 РЕЗУЛЬТАТЫ ТЕСТИРОВАНИЯ Parcelable Serializable Память 92 bytes 117 bytes

    Среднее время API 21 1 486 K 12 565 K Среднее время API 29 300 K 2 115 K + 27% + 605% + 745% Наносекунды
  54. 54 РЕЗУЛЬТАТЫ ТЕСТИРОВАНИЯ Parcelable Serializable Память 92 bytes 117 bytes

    Среднее время API 21 1 486 K 12 565 K Среднее время API 29 300 K 2 115 K + 27% + 605% + 745% Наносекунды
  55. 55 МИНУСЫ PARCELABLE

  56. 56 ИЗБАВИЛИСЬ ОТ РЕФЛЕКСИИ?

  57. 57 companion object CREATOR : Creator<Person> { ... } PARCELABLE

    БЕЗ РЕФЛЕКСИИ?
  58. 58 Field f = parcelableClass.getField("CREATOR"); PARCELABLE БЕЗ РЕФЛЕКСИИ? companion object

    CREATOR : Creator<Person> { .
  59. 59 val classLoader = Person : : class.java.classLoader val result

    = destination.readParcelable(classLoader) PARCELABLE БЕЗ РЕФЛЕКСИИ?
  60. 60 val classLoader = Person :

  61. 61 CLASSLOADERS

  62. 62 CLASSLOADERS В JAVA Bootstrap ClassLoader Extension ClassLoader Application ClassLoader

  63. 63 CLASSLOADERS В JAVA Bootstrap ClassLoader Extension ClassLoader Application ClassLoader

    Intent, Activity, FileOutputStream
  64. 64 CLASSLOADERS В JAVA Bootstrap ClassLoader Extension ClassLoader Application ClassLoader

    Intent, Activity, FileOutputStream Person, MyActivity
  65. 65 ВОССТАНОВЛЕНИЕ ОБЪЕКТА "com.myapplication.Person□John□Smith□"

  66. 66 "com.myapplication.Person□John□Smith□" "com.myapplication.Person" ВОССТАНОВЛЕНИЕ ОБЪЕКТА

  67. 67 "com.myapplication.Person□John□Smith□" "com.myapplication.Person" val clazz : Class<Person> ВОССТАНОВЛЕНИЕ ОБЪЕКТА

  68. 68 "com.myapplication.Person□John□Smith□" "com.myapplication.Person" val clazz : Class<Person> val person :

    Person ВОССТАНОВЛЕНИЕ ОБЪЕКТА
  69. 69 "com.myapplication.Person□John□Smith□" "com.myapplication.Person" val clazz : Class<Person> val person :

    Person ??? ??? ВОССТАНОВЛЕНИЕ ОБЪЕКТА
  70. 70 МЕТАДАННЫЕ КЛАССА val clazz: Class<Person> = Class.forName("com.myapplication.Person", CLASSLOADER?)

  71. 71 МЕТАДАННЫЕ КЛАССА val clazz: Class<Person> = Class.forName("com.myapplication.Person", CLASSLOADER?) Serializable

    Последний ClassLoader в стеке.
  72. 72 МЕТАДАННЫЕ КЛАССА val clazz: Class<Person> = Class.forName("com.myapplication.Person", CLASSLOADER?) Parcelizable

    Явно указывается. Serializable Последний ClassLoader в стеке.
  73. 73 ОГРАНИЧЕНИЯ PARCELABLE?

  74. 74 ПЕРЕДАЧА ДАННЫХ ЧЕРЕЗ BUNDLE Activity A Activity B Name

    John Surname Smith Bundle Name ... Surname ... Bundle
  75. 75 СОБЕСЕДОВАНИЕ У Bundle есть ограничение в 1 мегабайт! 👨💻

    Кандидат
  76. 76 ДАННЫЕ ЧЕРЕЗ IBINDER Activity A Activity B Name John

    Surname Smith Age 24 Salary $1.000 Job Age City Moscow Pet Dog Rating 4.8 Bundle Bundle Name ... Surname ... Age ... Salary ... Job ... City ... Pet ... Rating ... IBinder
  77. 77 ДАННЫЕ ЧЕРЕЗ IBINDER Activity A Activity B Name John

    Surname Smith Age 24 Salary $1.000 Job Age City Moscow Pet Dog Rating 4.8 Bundle Bundle IBinder Name ... Surname ... Age ... Salary ... Job ... City ... Pet ... Rating ... TransactionTooLargeException max 1 Mb
  78. 78 Часть 1 Serializable vs Parcelable Итог #1

  79. 79 SERIALIZABLE vs PARCELABLE Serializable Медленнее чем Parcelizable, можно сохранять

    в постоянное хранилище. Parcelizable Быстрая обработка, требует меньше места, используется для транзакций через IBinder. Нельзя использовать в постоянном хранилище. Нет ограничений.
  80. 80 Часть 2 Serializable Serializable Serializable ЧАСТЬ 2

  81. 81 ИЗМЕНЕНИЕ СИГНАТУРЫ КЛАССА ?? sr*com.myapplication.Person ?? T»1? IageLnametLjava/lang/String;L surnameq~xptJohntSmith

    Bytes class Person( val name: String, val surname: String, val age: Int, ) : Serializable class Person( val name: String, val NEW_NAME: String, val age: Int, ) : Serializable . . . . . . . . . . .
  82. 82 ЧТЕНИЕ С ДРУГОЙ СИГНАТУРОЙ Parcel Name John NEW_NAME Age

    21
  83. 83 ID СИГНАТУРЫ КЛАССА class Person( private val name: String,

    private val surname: String, private val age: Int, ) : Serializable { companion object { const val serialVersionUID = -48629433707L } } companion object { const val serialVersionUID = -48629433707L }
  84. 84 ИЗМЕНЕНИЕ СИГНАТУРЫ КЛАССА ?? sr*com.myapplication.Person ?? T»1? IageLnametLjava/lang/String;L surnameq~xptJohntSmith

    Bytes class Person( val name: String, val surname: String, val age: Int, ) : Serializable class Person( val name: String, val NEW_NAME: String, val age: Int, ) : Serializable . . . . . . . . InvalidClassException
  85. 85 ИЗМЕНЕНИЕ СИГНАТУРЫ КЛАССА class Person( val name: String, val

    NEW_NAME: String, val age: Int, ) : Serializable ?? sr*com.myapplication.Person ?? T»1? IageLnametLjava/lang/String;L surnameq~xptJohntSmith serialVersionUID serialVersionUID ==
  86. 86 ИЗМЕНЕНИЕ СИГНАТУРЫ КЛАССА class Person( val name: String, val

    surname: String, val age: Int, ) : Serializable ?? sr*com.myapplication.Person ?? IageLnametLjava/lang/String;L surnameq~xptJohntSmith 48629433707 70733492684 x
  87. 87 РУЧНОЕ УПРАВЛЕНИЕ СЕРИАЛИЗАЦИЕЙ

  88. 88 РУЧНАЯ СЕРИАЛИЗАЦИЯ class Person( private val name: String, private

    val surname: String, @Transient private val age: Int, ) : Serializable { companion object { const val serialVersionUID = -48629433707L } } TRANSIENT Поле, не помеченное этим ключевым словом, не будет подвергаться сериализации. @Transient
  89. 89 ЧТЕНИЕ С ДРУГОЙ СИГНАТУРОЙ Parcel Name John Surname Smith

    Age
  90. 90 БОЛЕЕ ДЕТАЛЬНОЕ УПРАВЛЕНИЕ СЕРИАЛИЗАЦИЕЙ

  91. 91 БОЛЕЕ ДЕТАЛЬНОЕ УПРАВЛЕНИЕ СЕРИАЛИЗАЦИЕЙ EXTERNALIZABLE Расширение Serializable с обязательным

    переопределением методов чтения и записи объекта. Наличие пустого конструктора обязательно! class Person( private var name: String, private var surname: String, private var age: Int, ) : Externalizable { constructor() : this("", "", 0) override fun writeExternal(out: ObjectOutput) { out.writeObject(name) out.writeObject(surname) out.writeInt(age) } override fun readExternal(`in`: ObjectInput) { name = `in`.readObject() as String surname = `in`.readObject() as String age = `in`.readInt() } }
  92. 92 БОЛЕЕ ДЕТАЛЬНОЕ УПРАВЛЕНИЕ СЕРИАЛИЗАЦИЕЙ EXTERNALIZABLE Расширение Serializable с обязательным

    переопределением методов чтения и записи объекта. Наличие пустого конструктора обязательно! class Person( private var name: String, private var surname: String, private var age: Int, ) : Externalizable { constructor() : this("", "", 0) override fun writeExternal(out: ObjectOutput) { out.writeObject(name) out.writeObject(surname) out.writeInt(age) } override fun readExternal(`in`: ObjectInput) { name = `in`.readObject() as String surname = `in`.readObject() as String age = `in`.readInt() } } override fun writeExternal(out: ObjectOutput) { out.writeObject(name) out.writeObject(surname) out.writeInt(age) } override fun readExternal(`in`: ObjectInput) { name = `in`.readObject() as String surname = `in`.readObject() as String age = `in`.readInt() }
  93. 93 БОЛЕЕ ДЕТАЛЬНОЕ УПРАВЛЕНИЕ СЕРИАЛИЗАЦИЕЙ EXTERNALIZABLE Расширение Serializable с обязательным

    переопределением методов чтения и записи объекта. Наличие пустого конструктора обязательно! class Person( private var name: String, private var surname: String, private var age: Int, ) : Externalizable { constructor() : this("", "", 0) override fun writeExternal(out: ObjectOutput) { out.writeObject(name) out.writeObject(surname) out.writeInt(age) } override fun readExternal(`in`: ObjectInput) { name = `in`.readObject() as String surname = `in`.readObject() as String age = `in`.readInt() } } constructor() : this("", "", 0)
  94. 94 РЕЗУЛЬТАТЫ ТЕСТИРОВАНИЯ Parcelable Serializable Externalizable Память 92 bytes 117

    bytes 68 bytes Среднее время API 21 1 486 K 12 565 K 4 189 K Среднее время API 29 300 K 2 115 K 695 K + 27% - 28% + 605% + 131% + 181% + 745%
  95. 95 БОЛЕЕ ДЕТАЛЬНОЕ УПРАВЛЕНИЕ СЕРИАЛИЗАЦИЕЙ У SERIALIZABLE

  96. 96 БОЛЕЕ ДЕТАЛЬНОЕ УПРАВЛЕНИЕ СЕРИАЛИЗАЦИЕЙ WRITEOBJECT / READOBJECT Ручное управление

    чтения/ записи с возможностью расширения чтения/записи по умолчанию. class Person( private var name: String, private var surname: String, private var age: Int, ) : Serializable { private fun writeObject(out: ObjectOutputStream) { out.defaultWriteObject() out.writeInt(42) } private fun readObject(`in`: ObjectInputStream) { `in`.defaultReadObject() `in`.readInt() / / 42 }
  97. 97 БОЛЕЕ ДЕТАЛЬНОЕ УПРАВЛЕНИЕ СЕРИАЛИЗАЦИЕЙ WRITEOBJECT / READOBJECT Ручное управление

    чтения/ записи с возможностью расширения чтения/записи по умолчанию. class Person( private var name: String, private var surname: String, private var age: Int, ) : Serializable { private fun writeObject(out: ObjectOutputStream) { out.defaultWriteObject() out.writeInt(42) } private fun readObject(`in`: ObjectInputStream) { `in`.defaultReadObject() `in`.readInt() /
  98. 98 БОЛЕЕ ДЕТАЛЬНОЕ УПРАВЛЕНИЕ СЕРИАЛИЗАЦИЕЙ WRITEOBJECT / READOBJECT Ручное управление

    чтения/ записи с возможностью расширения чтения/записи по умолчанию. class Person( private var name: String, private var surname: String, private var age: Int, ) : Serializable { private fun writeObject(out: ObjectOutputStream) { out.defaultWriteObject() out.writeInt(42) } private fun readObject(`in`: ObjectInputStream) { `in`.defaultReadObject() `in`.readInt() / / 42
  99. 99 Serializable ( writeObject / readObject ) Transient 01. Externalizable

    02. 03. РУЧНАЯ СЕРИАЛИЗАЦИЯ
  100. « Android Developer paborzikov@avito.ru @elvisfromsouth @elvisfromsouth Спасибо за внимание Москва

    — 2021 Павел Борзиков