Почему Java имеет переходные поля?
Почему у Java есть переходные поля?
Ответы
Ответ 1
Ключевое слово transient
в Java используется, чтобы указать, что поле не должно быть частью процесса сериализации (что означает сохранение, как в файл).
Из спецификации языка Java, Java SE 7 Edition, раздел 8.3.1.3. transient
поля:
Переменные могут быть помечены как transient
чтобы указать, что они не являются частью постоянного состояния объекта.
Например, у вас могут быть поля, которые являются производными от других полей, и их следует делать только программно, а не сохранять состояние посредством сериализации.
Вот класс GalleryImage
который содержит изображение и эскиз, полученный из изображения:
class GalleryImage implements Serializable
{
private Image image;
private transient Image thumbnailImage;
private void generateThumbnail()
{
// Generate thumbnail.
}
private void readObject(ObjectInputStream inputStream)
throws IOException, ClassNotFoundException
{
inputStream.defaultReadObject();
generateThumbnail();
}
}
В этом примере thumbnailImage
- это миниатюрное изображение, которое генерируется с помощью вызова метода generateThumbnail
.
Поле thumbnailImage
помечается как transient
, поэтому сериализуется только исходное image
а не сохраняется как исходное изображение, так и уменьшенное изображение. Это означает, что для сохранения сериализованного объекта потребуется меньше места. (Конечно, это может или не может быть желательно в зависимости от требований системы - это только пример.)
Во время десериализации метод readObject
вызывается для выполнения любых операций, необходимых для восстановления состояния объекта обратно в состояние, в котором произошла сериализация. Здесь, миниатюра должна быть сгенерирована, поэтому метод readObject
переопределяется, так что миниатюра будет сгенерирована путем вызова метода generateThumbnail
.
Для получения дополнительной информации статья " Раскройте секреты API-интерфейса Java Serialization" (которая первоначально была доступна в Sun Developer Network) содержит раздел, в котором обсуждается использование и представлен сценарий, в котором ключевое слово transient
используется для предотвращения сериализации определенных полей.
Ответ 2
Прежде чем понять transient
ключевое слово, нужно понять концепцию сериализации. Если читатель знает о сериализации, пропустите первый пункт.
Что такое сериализация?
Сериализация - это процесс сохранения состояния объекта. Это означает, что состояние объекта преобразуется в поток байтов, который используется для сохранения (например, для хранения байтов в файле) или для передачи (например, для отправки байтов по сети). Таким же образом, мы можем использовать десериализацию, чтобы вернуть состояние объекта из байтов. Это одна из важных концепций в Java-программировании, потому что сериализация в основном используется в сетевом программировании. Объекты, которые должны быть переданы через сеть, должны быть преобразованы в байты. Для этой цели каждый класс или интерфейс должен реализовывать интерфейс Serializable
. Это маркерный интерфейс без каких-либо методов.
Теперь, что такое transient
ключевое слово и его назначение?
По умолчанию все переменные объекта преобразуются в постоянное состояние. В некоторых случаях вы можете избежать сохранения некоторых переменных, потому что вам не нужно сохранять эти переменные. Таким образом, вы можете объявить эти переменные как transient
. Если переменная объявлена как transient
, она не будет сохранена. Это основная цель transient
ключевого слова.
Я хочу объяснить вышеупомянутые два пункта следующим примером:
package javabeat.samples;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class NameStore implements Serializable{
private String firstName;
private transient String middleName;
private String lastName;
public NameStore (String fName, String mName, String lName){
this.firstName = fName;
this.middleName = mName;
this.lastName = lName;
}
public String toString(){
StringBuffer sb = new StringBuffer(40);
sb.append("First Name : ");
sb.append(this.firstName);
sb.append("Middle Name : ");
sb.append(this.middleName);
sb.append("Last Name : ");
sb.append(this.lastName);
return sb.toString();
}
}
public class TransientExample{
public static void main(String args[]) throws Exception {
NameStore nameStore = new NameStore("Steve", "Middle","Jobs");
ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("nameStore"));
// writing to object
o.writeObject(nameStore);
o.close();
// reading from object
ObjectInputStream in = new ObjectInputStream(new FileInputStream("nameStore"));
NameStore nameStore1 = (NameStore)in.readObject();
System.out.println(nameStore1);
}
}
И вывод будет следующим:
First Name : Steve
Middle Name : null
Last Name : Jobs
Второе имя объявляется transient
, поэтому оно не будет храниться в постоянном хранилище.
Источник
Ответ 3
Чтобы позволить вам определить переменные, которые вы не хотите сериализовать.
В объекте у вас может быть информация, которую вы не хотите сериализовать/сохранять (возможно, ссылка на родительский объект фабрики), или, возможно, нет смысла сериализовать. Отметив их как "переходные" означает, что механизм сериализации будет игнорировать эти поля.
Ответ 4
Мой небольшой вклад:
Что такое переходное поле?
В принципе, любое поле, измененное ключевым словом transient
является переходным полем.
Почему в Java необходимы временные поля?
Ключевое слово transient
дает вам некоторый контроль над процессом сериализации и позволяет исключить некоторые свойства объекта из этого процесса. Процесс сериализации используется для сохранения объектов Java, главным образом для сохранения их состояний во время их передачи или бездействия. Иногда имеет смысл не сериализовывать определенные атрибуты объекта.
В каких полях следует отмечать переходные процессы?
Теперь мы знаем цель transient
ключевого слова и переходных полей, важно знать, какие поля отмечать переходные процессы. Статические поля также не сериализуются, поэтому соответствующее ключевое слово также будет делать трюк. Но это может испортить ваш классный дизайн; это то, где ключевое слово transient
приходит на помощь. Я стараюсь не разрешать поля, значения которых могут быть получены из других, чтобы быть сериализованными, поэтому я отмечаю их переходные. Если у вас есть поле под названием " interest
, значение которого может быть вычислено из других полей (principal
, rate
и time
), сериализация его не требуется.
Другим хорошим примером является подсчет слов статьи. Если вы сохраняете целую статью, нет необходимости сохранять число слов, потому что оно может быть вычислено, когда статья становится "десериализованной". Или подумайте о лесозаготовителей; Logger
случаи почти никогда не нужно сериализовать, поэтому они могут быть сделаны преходящее.
Ответ 5
transient
переменная - это переменная, которая не может быть сериализована.
Одним из примеров того, когда это может быть полезно, что приходит на ум, являются переменные, которые имеют смысл только в контексте конкретного экземпляра объекта и которые становятся недействительными после того, как вы сериализовали и десериализовали объект. В этом случае полезно, чтобы эти переменные стали null
чтобы вы могли повторно инициализировать их полезными данными, когда это необходимо.
Ответ 6
transient
используется, чтобы указать, что поле класса не нужно сериализовать.
Вероятно, лучшим примером является поле Thread
. Обычно нет причин для сериализации Thread
, поскольку его состояние очень "специфично для потока".
Ответ 7
Системы сериализации, отличные от родной Java, также могут использовать этот модификатор. Например, Hibernate не будет сохранять поля, отмеченные как @Transient, так и модификатором переходного. Терракота также уважает этот модификатор.
Я считаю, что образный смысл модификатора - это "это поле для использования только в памяти". Не сохраняйте или не перемещайте его за пределы этой конкретной виртуальной машины каким-либо образом. т.е. вы не можете полагаться на его значение в другом пространстве памяти VM. Подобно volatile, вы не можете полагаться на определенную семантику памяти и семантики.
Ответ 8
Сериализация - это процесс сохранения состояний объектов в постоянном формате (например, поток файлов или базы данных) и последующее восстановление их из потока (де-сериализация).
В Java объект класса сериализуется, если класс реализует интерфейс java.io.Serializable. Это интерфейс маркера, который сообщает JVM, что класс имеет право на сериализацию.
public class User implements Serializable {
private static final long serialVersionUID = 1234L;
private String username;
private String email;
private transient String password;
private Date birthday;
private int age;
public User(String username, String email, String password, Date birthday,
int age) {
this.username = username;
this.email = email;
this.password = password;
this.birthday = birthday;
this.age = age;
}
public void printInfo() {
System.out.println("username: " + username);
System.out.println("email: " + email);
System.out.println("password: " + password);
System.out.println("birthday: " + birthday);
System.out.println("age: " + age);
}
// getters and setters
}
В этом классе модели есть три важных момента:
Он должен реализовывать интерфейс Serializable. В противном случае, получите java.io.NotSerializableException при попытке сериализации объекта класса.
Константа с именем serialVersionUID объявляется и назначается длинное значение:
private static final long serialVersionUID = 1234L;
Это обычная константа, которая должна быть объявлена, когда класс реализует интерфейс Serializable. Серийная версия UID решительно обеспечивает совместимость сериализованных и де-сериализованных версий объектов класса, поскольку процесс сериализации и де-сериализации может происходить на разных компьютерах и в системах. Хотя это объявление является необязательным, его всегда рекомендуется объявлять serialVersionUID для сериализуемого класса.
Обратите внимание, что поле пароля отмечено как переходное:
private transient String password;
Потому что мы не хотим хранить пароль при сериализации объекта. Правило заключается в том, что когда переменная отмечена как переходная, ее объект не будет сериализован во время сериализации.
Переменная - переменная, которая не может быть сериализована. Вы используете ключевое слово transient, чтобы указать виртуальной машине Java, что указанная переменная не является частью постоянного состояния объекта.
Модификаторы доступа, поддерживаемые Java, являются статическими, окончательными, абстрактными, синхронизированными, нативными, летучими, переходными и strictfp.
В следующей таблице приведен список спецификаторов доступа и модификаторов Java, которые могут применяться к переменным, методам и классам.
SPECIFIER/MODIFIER LOCAL VARIABLE INSTANCEVARIABLE METHOD CLASS
public NA A A A
protected NA A A NA
default A A A A
private NA A A NA
final A A A A
static NA A A NA
synchronized NA NA A NA
native NA NA A NA
volatile NA A NA NA
transient NA A NA NA
strictfp NA NA A A
Ответ 9
Поскольку не все переменные имеют сериализуемую природу
Ответ 10
Прежде чем ответить на этот вопрос, я должен объяснить вам SERIALIZATION, потому что, если вы понимаете, что означает сериализацию в научном компьютере, вы можете легко понять это ключевое слово.
Сериализация
Когда объект передается через сеть/сохраняется на физическом носителе (файл,...), объект должен быть "сериализован". Сериализация преобразует ряды объектов состояния байтов. Эти байты отправляются в сети/сохраняются, и объект заново создается из этих байтов.
Пример
public class Foo implements Serializable
{
private String attr1;
private String attr2;
...
}
Теперь, если вы не хотите TRANSFERT/ SAVED этого объекта SO, вы можете использовать ключевое слово > transient
private transient attr2;
Пример
Ответ 11
Это необходимо, когда вы не хотите делиться конфиденциальными данными, которые идут с сериализацией.
Ответ 12
Согласно переходному значению Google == длительность только в течение короткого времени; непостоянно.
Теперь, если вы хотите сделать что-то временное в Java, используйте ключевое слово transient.
Q: где использовать переходный процесс?
A: Обычно в java мы можем сохранять данные в файлы, собирая их в переменные и записывая эти переменные в файлы, этот процесс известен как сериализация. Теперь, если мы хотим избежать записи переменных данных в файл, мы бы сделали эту переменную временной.
transient int result=10;
Примечание: временные переменные не могут быть локальными.
Ответ 13
Проще говоря, переходное ключевое слово java защищает поля от Serialize в качестве их счетчиков противоположных полей.
В этом фрагменте кода наш абстрактный класс BaseJob реализует интерфейс Serializable, мы распространяемся от BaseJob, но нам не нужно сериализовать удаленные и локальные источники данных; сериализуйте только теги organizationName и isSynced.
public abstract class BaseJob implements Serializable{
public void ShouldRetryRun(){}
}
public class SyncOrganizationJob extends BaseJob {
public String organizationName;
public Boolean isSynced
@Inject transient RemoteDataSource remoteDataSource;
@Inject transient LocalDaoSource localDataSource;
public SyncOrganizationJob(String organizationName) {
super(new
Params(BACKGROUND).groupBy(GROUP).requireNetwork().persist());
this.organizationName = organizationName;
this.isSynced=isSynced;
}
}
Ответ 14
Дайте еще один пример, чтобы прояснить ситуацию. Пожалуйста, прочитайте принятый ответ. Здесь я буду объяснять только еще один пример.
class Employee{
String name;
Date dob;
transient int age;
public int calculateAge(Date dob){
int age = 0;
//calculate age based on Date of birth
return age;
}
}
Здесь в приведенном выше примере я сделал "возраст" как переходный. Когда я записываю возраст в файл, его значение не нужно хранить. У меня есть функция, которая рассчитывает возраст на основе DOB. Мы можем использовать переменные для тех переменных-членов, которых мы не хотим записывать на диск.
Надеюсь, поможет.!
Ответ 15
Упрощенный пример кода для переходного ключевого слова.
import java.io.*;
class NameStore implements Serializable {
private String firstName, lastName;
private transient String fullName;
public NameStore (String fName, String lName){
this.firstName = fName;
this.lastName = lName;
buildFullName();
}
private void buildFullName() {
// assume building fullName is compuational/memory intensive!
this.fullName = this.firstName + " " + this.lastName;
}
public String toString(){
return "First Name : " + this.firstName
+ "\nLast Name : " + this.lastName
+ "\nFull Name : " + this.fullName;
}
private void readObject(ObjectInputStream inputStream)
throws IOException, ClassNotFoundException
{
inputStream.defaultReadObject();
buildFullName();
}
}
public class TransientExample{
public static void main(String args[]) throws Exception {
ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("ns"));
o.writeObject(new NameStore("Steve", "Jobs"));
o.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("ns"));
NameStore ns = (NameStore)in.readObject();
System.out.println(ns);
}
}