предисловиеЧестно говоря, друзья, которые какое-то время изучали Java,transient
Это ключевое слово все еще очень незнакомо и почти не используется, ноtransient
Ключевые слова играют незаменимую роль в Java! Если вы хотите поговорить об этом, я думаю, что наиболее вероятным местом будет упоминание потока объектов (также называемого потоком сериализации) в потоке ввода-вывода!
Я считаю, что многие люди не будут заботиться об этом ключевом слове, пока не столкнутся с ним, я помню, как блогер впервые столкнулся с ним.transient
Ключевое слово — при чтении исходного кода JDK. в процессе изучения javatransient
Причина редкости ключевого слова на самом деле неотделима от его роли:transient
Основная функция ключевых слов заключается в том, чтобы убедиться, чтоПеременные свойства члена, измененные ключевым словом transient, не сериализуются.. Собственно, именно по этой причине операции сериализации редко используются в процессе обучения, вообще в реальной разработке! Что касается сериализации, я считаю, что есть много маленьких белых детских ботинок, которые запутались или не имеют конкретной концепции.Утрированно, немного притворяясь б, чувствую, что меня сейчас прибьют)
@[toc]
1. Что такое сериализация?
Говоря о сериализации, еще одна концепция, которая следует за этим, — десериализация. .
Сериализация определена техническими терминами:
Java предоставляет механизм сериализации объектов. Объект может быть представлен последовательностью байтов, которая содержит такую информацию, как данные объекта, тип объекта и свойства, хранящиеся в объекте. После записи последовательности байтов в файл это эквивалентно сохранению информации об объекте в файле. И наоборот, последовательность байтов также может быть считана из файла, реконструируя объект и десериализуя его. Данные объекта, тип объекта и информация о данных, хранящаяся в объекте, могут использоваться для создания объекта в памяти.
Термин Ичуня определяет сериализацию:
Сериализация:байты --> объект
По сути, то, что я сделал, это вышеприведенный вывод. Если вы не понимаете, то можете прямо обратиться к определению профессиональных терминов. Поняв, просто запомните мои слова. Если не можете вспомнить, пожалуйста, убейте меня (я я просто гений когда пинаю м)
График понимания сериализации:
2. Зачем сериализовать?
Из концепции сериализации, упомянутой в предыдущем разделе, после знакомства с концепцией мы должны понять, зачем нужна сериализация.
Прежде чем говорить о том, зачем нужна сериализация, блогер даст мне каштан:
Точно так же, как когда вы идете на улицу, чтобы купить овощи, основная операция состоит в том, чтобы упаковать их в полиэтиленовые пакеты и взять их, когда вы идете домой, чтобы готовить. И эта серия операций похожа на сериализацию и десериализацию!
Сериализация объектов в Java относится к преобразованию объектов в последовательности байтов, которые содержат данные и информацию об объекте.Может быть записан в базу данных или файл, также можно использовать дляпередача по сети, как правило, когда мы используемкеш-кэш(Локально на жестком диске может быть недостаточно места в памяти) илиудаленный вызов rpc(передача по сети), нам часто нужно, чтобы наш класс сущности реализовывалSerializable
Интерфейс, цель состоит в том, чтобы сделать его сериализуемым.
- во время разработкииспользовать переходныйКаштаны с измененным ключевым словом:
Если у пользователя есть какие-то пароли и другая информация, в целях безопасности они не хотят передаваться во время сетевых операций, переменные, соответствующие этой информации, могут быть добавлены с ключевым словом transient.Другими словами, время жизни этого поля существует только в памяти вызывающего объекта и не будет записано на диск для сохранения.
- во время разработкинет необходимости в переходномКаштаны с измененным ключевым словом:
1. Значения полей в классе могут быть получены из других полей. 2. В зависимости от конкретных бизнес-требований, какие поля не нужно сериализовать;
Я не знаю, задумывались ли вы о том, почему его нельзя сериализовать? На самом деле, это в основном для экономии места для хранения. Оптимизатор!
PS: не забудьте посмотреть перед
HashMap
Когда я получил исходный код, я обнаружил, что есть поле, которое используетtransient
Модифицировано, я думаю, это имеет смысл. На самом деле нет необходимости сериализовать это поле modCount, потому что оно бессмысленно. modCount в основном используется для определения того, был ли изменен HashMap (например, операции ввода и удаления,modCount
Он будет самовозрастающим), для такого рода переменных это может быть любое значение в начале, конечно, 0 тоже может быть (новое, десериализованное или клонированное - все 0), нет необходимости сохранять его значение .
Конечно, конечной целью сериализации является десериализация и восстановление исходного объекта Java. В противном случае, что бы вы делали после сериализации? пластиковый пакет. , поэтому сериализованную последовательность байтов можно восстановить в объект Java, и этот процесс называется десериализацией.
3. Сериализация и использование переходных
1,Класс объекта, который необходимо сериализовать, должен реализовывать интерфейс сериализации: Java.lang.Serializable interface(интерфейс флага, без каких-либо абстрактных методов), большинство классов в Java реализуют этот интерфейс, например:String
,Integer
классы и т. д., классы, которые не реализуют этот интерфейс, не будут иметь никакого сериализованного или десериализованного состояния и будут выдаватьNotSerializableException
исключение.
2, нижний слой будет судить, если текущий объектSerializable
Экземпляры объектов Java могут выполнять сериализацию толькоinstanceof Serializable
судить.
3,Использование потоков объектов в JavaObjectOutputStream
завершить сериализацию иObjectInputStream
Потоковая десериализация
-
==ObjectOutputStream: сериализовать через метод writeObject() ==
-
==ObjectInputStream: десериализовать через метод readObject()==
4. Все свойства класса должны быть сериализуемыми. Если есть свойство, которое не нужно сериализовать, свойство должно быть помечено как временное, используйтеtransient
Модификация ключевого слова.
Здесь я действительно настоятельно рекомендую читателям и друзьям, которые читают блог Ичуня, попробуйте постучать, не забудьте взять его или скопировать и запустить с первого взгляда, особенно детскую обувь Xiaobai, поверьте мне! Вы обязательно получите что-то другое. Не думайте, что это пустая трата времени, иногда медленное — это быстрое, испытайте это на себе Ичунь!
3.1 Сериализация без реализации интерфейса Serializable
package TransientTest;
import java.io.*;
class UserInfo { //================================注意这里没有实现Serializable接口
private String name;
private transient String password;
public UserInfo(String name,String psw) {
this.name = name;
this.password=psw;
}
@Override
public String toString() {
return "UserInfo{" +
"name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
public class TransientDemo {
public static void main(String[] args) {
UserInfo userInfo=new UserInfo("老王","123");
System.out.println("序列化之前信息:"+userInfo);
try {
ObjectOutputStream output=new ObjectOutputStream(new FileOutputStream("userinfo.txt"));
output.writeObject(new UserInfo("老王","123"));
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
результат операции
3.2 Реализация сериализации интерфейса Serializable
Когда мы добавим реализацию интерфейса Serializable, а затем запустим ее, мы обнаружим, что элементы, которые появляются в проектеuserinfo.txt
Содержимое файла такое:
3.3 Общая ситуация с сериализацией
package TransientTest;
import java.io.*;
class UserInfo implements Serializable{ //第一步实现Serializable接口
private String name;
private String password;//都是普通属性==============================
public UserInfo(String name,String psw) {
this.name = name;
this.password=psw;
}
@Override
public String toString() {
return "UserInfo{" +
"name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
public class TransientDemo {
public static void main(String[] args) throws ClassNotFoundException {
UserInfo userInfo=new UserInfo("程序员老王","123");
System.out.println("序列化之前信息:"+userInfo);
try {
ObjectOutputStream output=new ObjectOutputStream(new FileOutputStream("userinfo.txt")); //第二步开始序列化操作
output.writeObject(new UserInfo("程序员老王","123"));
output.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
ObjectInputStream input=new ObjectInputStream(new FileInputStream("userinfo.txt"));//第三步开始反序列化操作
Object o = input.readObject();//ObjectInputStream的readObject方法会抛出ClassNotFoundException
System.out.println("序列化之后信息:"+o);
} catch (IOException e) {
e.printStackTrace();
}
}
}
результат операции:
序列化之前信息:UserInfo{name='程序员老王', password='123'}
序列化之后信息:UserInfo{name='程序员老王', password='123'}
3.4, переходная ситуация с сериализацией
package TransientTest;
import java.io.*;
class UserInfo implements Serializable{ //第一步实现Serializable接口
private String name;
private transient String password; //特别注意:属性由transient关键字修饰===========
public UserInfo(String name,String psw) {
this.name = name;
this.password=psw;
}
@Override
public String toString() {
return "UserInfo{" +
"name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
public class TransientDemo {
public static void main(String[] args) throws ClassNotFoundException {
UserInfo userInfo=new UserInfo("程序员老王","123");
System.out.println("序列化之前信息:"+userInfo);
try {
ObjectOutputStream output=new ObjectOutputStream(new FileOutputStream("userinfo.txt")); //第二步开始序列化操作
output.writeObject(new UserInfo("程序员老王","123"));
output.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
ObjectInputStream input=new ObjectInputStream(new FileInputStream("userinfo.txt"));//第三步开始反序列化操作
Object o = input.readObject();//ObjectInputStream的readObject方法会抛出ClassNotFoundException
System.out.println("序列化之后信息:"+o);
} catch (IOException e) {
e.printStackTrace();
}
}
}
результат операции:
序列化之前信息:UserInfo{name='程序员老王', password='123'}
序列化之后信息:UserInfo{name='程序员老王', password='null'}
Обратите особое внимание на результаты, добавив переходные модификаторы к значениям по умолчанию.null
! Если модифицируемое transient свойство имеет тип int, то после сериализации его значение должно быть равно 0. Конечно, можно попробовать, что это значит? Описание помечено какtransient
Свойства объекта не будут сохранены при сериализации объекта (или переменная не будет сохранена)
3.5, ситуация статической сериализации
package TransientTest;
import java.io.*;
class UserInfo implements Serializable{ //第一步实现Serializable接口
private String name;
private static String password; //特别注意:属性由static关键字修饰==============
public UserInfo(String name, String psw) {
this.name = name;
this.password=psw;
}
@Override
public String toString() {
return "UserInfo{" +
"name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
public class TransientDemo {
public static void main(String[] args) throws ClassNotFoundException {
UserInfo userInfo=new UserInfo("程序员老王","123");
System.out.println("序列化之前信息:"+userInfo);
try {
ObjectOutputStream output=new ObjectOutputStream(new FileOutputStream("userinfo.txt")); //第二步开始序列化操作
output.writeObject(new UserInfo("程序员老王","123"));
output.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
ObjectInputStream input=new ObjectInputStream(new FileInputStream("userinfo.txt"));//第三步开始反序列化操作
Object o = input.readObject();//ObjectInputStream的readObject方法会抛出ClassNotFoundException
System.out.println("序列化之后信息:"+o);
} catch (IOException e) {
e.printStackTrace();
}
}
}
результат операции:
序列化之前信息:UserInfo{name='程序员老王', password='123'}
序列化之后信息:UserInfo{name='程序员老王', password='123'}
В этот раз вы ошибочно подумаете, что статическая модификация тоже сериализуется, на самом деле это не так, на самом деле здесь легко запутаться! очевидно вынутьnull
(значение по умолчанию) может указывать на то, что он не будет сериализован.Это явно не значение по умолчанию здесь, почему вы это говорите?static
не будет сериализован?
На самом деле значение имени статической переменной в классе после десериализации на самом деле является значением соответствующей статической переменной в текущей JVM, которая находится в JVM и не является производной от десериализации.То есть переменные, измененные статическим, не участвуют в сериализации! Но мы не можем просто сказать, что это голословно, да, тогда давайте посмотрим на две программы и сравним их, чтобы понять!
Первая программа: Это программа атрибута имени, которая не модифицируется статическими:
package Thread;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class UserInfo implements Serializable {
private String name;
private transient String psw;
public UserInfo(String name, String psw) {
this.name = name;
this.psw = psw;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPsw() {
return psw;
}
public void setPsw(String psw) {
this.psw = psw;
}
public String toString() {
return "name=" + name + ", psw=" + psw;
}
}
public class TestTransient {
public static void main(String[] args) {
UserInfo userInfo = new UserInfo("程序员老过", "456");
System.out.println(userInfo);
try {
// 序列化,被设置为transient的属性没有被序列化
ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("UserInfo.txt"));
o.writeObject(userInfo);
o.close();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
try {
//在反序列化之前改变name的值 =================================注意这里的代码
userInfo.setName("程序员老改");
// 重新读取内容
ObjectInputStream in = new ObjectInputStream(new FileInputStream("UserInfo.txt"));
UserInfo readUserInfo = (UserInfo) in.readObject();
//读取后psw的内容为null
System.out.println(readUserInfo.toString());
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
результат операции:
name=程序员老过, psw=456
name=程序员老过, psw=null
Как видно из результатов работы программы, до десериализации программистов пытаются изменить старое значение изменений имени, результат не успешен!
Вторая программа: Это программа с измененным статическим атрибутом имени:
package Thread;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class UserInfo implements Serializable {
private static final long serialVersionUID = 996890129747019948L;
private static String name;
private transient String psw;
public UserInfo(String name, String psw) {
this.name = name;
this.psw = psw;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPsw() {
return psw;
}
public void setPsw(String psw) {
this.psw = psw;
}
public String toString() {
return "name=" + name + ", psw=" + psw;
}
}
public class TestTransient {
public static void main(String[] args) {
UserInfo userInfo = new UserInfo("程序员老过", "456");
System.out.println(userInfo);
try {
// 序列化,被设置为transient的属性没有被序列化
ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("UserInfo.txt"));
o.writeObject(userInfo);
o.close();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
try {
//在反序列化之前改变name的值
userInfo.setName("程序员老改");
// 重新读取内容
ObjectInputStream in = new ObjectInputStream(new FileInputStream("UserInfo.txt"));
UserInfo readUserInfo = (UserInfo) in.readObject();
//读取后psw的内容为null
System.out.println(readUserInfo.toString());
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
результат операции:
name=程序员老过, psw=456
name=程序员老改, psw=null
Из результатов работы программы видно, что перед десериализацией попробуйте изменить значение имени на старое изменение программиста, и результат будет успешным! Теперь понятно сравнивать две программы?
Свойства-члены, измененные с помощью ключевого слова static, лучше, чем нестатические свойства-члены, загруженные в память, а static также лучше, чем объекты, поступающие в память. Переменные-члены, измененные с помощью static, не могут быть сериализованы. Все сериализованные объекты являются объектами, а статические переменные — нет. . часть состояния объекта, поэтому он не участвует в сериализации. Поэтому бесполезно объявлять статические переменные переходными. Следовательно, значение имени статической переменной в классе после десериализации фактически является значением соответствующей статической переменной в текущей JVM, которая находится в JVM и не является производной от десериализации.
Если вы все еще не понимаете ключевое слово static, вы можете обратиться к этой статье, которую следует считать хорошей:Глубокое понимание статического ключевого слова
3.6, окончательная последовательность обстоятельств
Для окончательного ключевого слова Конечная переменная напрямую будет напрямую участвовать в сериализации через значение. Что касается кодовой программы, я больше не буду публиковать его. Вы можете попробовать использовать окончательную модификацию, чтобы проверить его!
Главное отметить, что final и transient могут изменять одну и ту же переменную одновременно, и результат один и тот же. Это не влияет на переходный процесс. В основном я упоминаю об этом здесь. Надеюсь, вы не будете сбиты с толку, когда встретите эти ситуации в будущем!
4. Роль serialVersionUID в классе java
Поскольку упоминается ключевое слово transient, необходимо упомянуть сериализацию, а поскольку упоминается сериализация, ее необходимо упомянуть.serialVersionUID
Теперь, что это? В основном этот serialVersionUID существует с сериализацией.
serialVersionUID
Механизм сериализации для Java. Проще говоря, механизм сериализации Java определяется классомserialVersionUID
Чтобы проверить согласованность версий. Во время десериализации JVM будет передавать поток байтовserialVersionUID
с локальным соответствующим классом сущностейserialVersionUID
Для сравнения, если они совпадают, то считаются непротиворечивыми и могут быть десериализованы, в противном случае произойдет исключение несогласованных сериализованных версий, т. е.InvalidCastException
, в разработке иногда может быть написано или нет, рекомендуется написать лучше.
5, сводка временных ключевых слов
1. Если переменная изменена переходным процессом, переменная не будет сериализована. 2. Ключевое слово transient может изменять только переменные, но не методы и классы. 3. Переменные, измененные ключевым словом static, не участвуют в сериализации Статическая переменная static не может быть сериализована независимо от того, изменена ли она переходным процессом. 4. Final значение переменной участвует в сериализации, а final transient одновременно модифицирует переменную Final не повлияет на переходную переменную и не будет участвовать в сериализации.
Второй момент, на который стоит обратить внимание, это то, что локальные переменные не могут быть изменены с помощью ключевого слова transient. Если переменная является определяемой пользователем переменной класса, класс должен реализовать интерфейс Serializable.
Обратите внимание, что третий момент: десериализованное значение статической переменной класса на самом деле является статической переменной, соответствующей текущему значению JVM, JVM это значение не является производным десериализованным.
Вывод:Изменение с помощью ключевого слова transient приводит к тому, что сериализация не выполняется, что позволяет экономить место для хранения. Оптимизатор! Далее следует, что поля, измененные переходным процессом, будут пересчитаны и инициализированы!
Если эта статья хоть немного вам поможет, то ставьте лайк, спасибо~
Если есть недочеты или неточности, прошу исправлять и критиковать, большое спасибо! Если у вас есть какие-либо вопросы, пожалуйста, оставьте сообщение и ответьте как можно скорее!
Наконец, вы можете обратить внимание на публичный аккаунт Ичуня, обсудить технологии вместе, тосковать по технологиям, заниматься технологиями, и вы станете другом, когда согласитесь...