Почему у Java есть временные поля?

Почему у Java есть временные поля?

26.05.2009 12:11:36
14 ОТВЕТОВ
РЕШЕНИЕ

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ключевое слово для предотвращения сериализации определенных полей.

1664
6.11.2018 15:54:11
Но почему это ключевое слово, а не аннотация @DoNotSerialize?
Elazar Leibovich 26.03.2011 21:46:48
Я думаю, это относится ко времени, когда в Java не было аннотаций.
Peter Wippermann 4.04.2011 13:48:15
Я нахожу странным, что сериализуемый является внутренним для Java. Он может быть реализован как интерфейс или абстрактный класс, который требует от пользователей переопределения методов чтения и записи.
caleb 17.02.2012 19:30:27
@MJafar: readObject обычно объединен в механизмы десериализации и поэтому вызывается автоматически. Кроме того, во многих случаях вам не нужно переопределять его - реализация по умолчанию делает свое дело.
Mike Adler 8.08.2013 07:36:11
@caleb, вероятно, потому что работа с двоичными форматами самостоятельно невероятно болезненна в Java из-за отсутствия целых чисел без знака.
rightfold 18.01.2014 22:19:30

Чтобы позволить вам определить переменные, которые вы не хотите сериализовать.

В объекте у вас может быть информация, которую вы не хотите сериализовать / сохранять (возможно, ссылка на родительский объект фабрики), или, возможно, нет смысла сериализовать. Отмечая их как «временные» означает, что механизм сериализации будет игнорировать эти поля.

83
14.02.2019 15:23:57

Потому что не все переменные имеют сериализуемую природу

9
26.05.2009 12:15:38
Пожалуйста, предоставьте больше информации, когда дадите ответ.
Danny Gloudemans 26.03.2014 15:30:42

transientПеременная является переменной , которая не может быть сериализации.

Один из примеров того, когда это может быть полезно, - это переменные, которые имеют смысл только в контексте конкретного экземпляра объекта и становятся недействительными после сериализации и десериализации объекта. В этом случае полезно, чтобы эти переменные стали nullвместо них, чтобы при необходимости вы могли повторно инициализировать их с полезными данными.

27
24.01.2018 05:47:49
да, что-то вроде членов поля «password or crediCardPin».
Mateen 20.02.2019 10:51:29

Это необходимо, когда вы не хотите делиться некоторыми конфиденциальными данными, которые идут с сериализацией.

6
26.05.2009 12:19:31
Существуют варианты использования, отличные от конфиденциальных данных, в которых вы можете не захотеть сериализовать поле. Например, вы, вероятно, никогда не захотите сериализовать Thread(например, кредит @AH), и в этом случае вы отметите его как временный. Однако поток сам по себе не является конфиденциальными данными, просто не имеет логического смысла его сериализовать (и он не сериализуем).
glen3b 9.05.2014 18:24:28
@ glen3b Этот случай не исключен этим ответом. Это, безусловно, необходимо, так как дела обстоят в случае, когда упоминается постер.
user207421 1.07.2015 13:32:00

Системы сериализации, кроме родной Java, также могут использовать этот модификатор. Например, Hibernate не сохранит поля, помеченные либо @Transient, либо модификатором transient . Терракота также уважает этот модификатор.

Я полагаю, что переносное значение модификатора таково: «Это поле предназначено только для использования в памяти. Не сохраняйте и не перемещайте его вне этой конкретной ВМ. Это непереносимо». то есть вы не можете полагаться на его значение в другом пространстве памяти виртуальной машины. Как и volatile, вы не можете полагаться на определенную семантику памяти и потоков.

15
28.05.2009 02:20:46
Я думаю, что transientэто не было бы ключевое слово, если бы оно было разработано в это время. Возможно, они будут использовать аннотацию.
Joachim Sauer 26.03.2010 14:13:53

transientиспользуется, чтобы указать, что поле класса не должно быть сериализовано. Вероятно, лучший пример - это Threadполе. Обычно нет причин для сериализации a Thread, поскольку его состояние очень специфично для потока.

17
26.11.2013 22:53:52
Поправьте меня, если я ошибаюсь, но Thread не сериализуем, так что он все равно будет пропущен?
TFennis 23.07.2013 10:54:25
@TFennis: Если сериализуемый класс Aссылается на не сериализуемый класс B(как Threadв вашем примере), то Aдолжен либо пометить ссылку, так как transientXOR должен переопределить процесс сериализации по умолчанию, чтобы сделать что-то разумное с BXOR, предполагая, что только сериализуемые подклассы Bфактически ссылаются (поэтому фактический подкласс должен заботиться об их «плохом» родителе B) XOR признает, что сериализация не удастся. Только в одном случае (помечен как переходный) Bавтоматически и тихо пропускается.
A.H. 26.11.2013 22:45:21
@TFennis Нет, это вызовет исключение.
user207421 1.07.2015 13:30:44
@AH: почему XOR? Я бы подумал, что код, который выполнял любую комбинацию этих вещей, работал бы, и некоторые комбинации могли бы быть полезными (например, переопределение процесса сериализации по умолчанию может быть полезным, даже если упоминаются только сериализуемые подклассы B, и наоборот).
supercat 13.05.2017 15:47:42

Прежде чем понять 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, поэтому оно не будет храниться в постоянном хранилище.

Источник

431
14.02.2019 14:48:21
Этот пример взят из этого кода, вы можете прочитать его здесь: javabeat.net/2009/02/what-is-transient-keyword-in-java
Krishna 20.11.2012 10:43:21
Эта часть кажется мне странной и, возможно, сбивающей с толку: «Это означает, что состояние объекта преобразуется в поток байтов и сохраняется в файле ». Мне кажется, что в большинстве случаев сериализация не связана с записью в файл (наглядный пример: примеры сетевых подключений)
Garcia Hurtado 24.11.2014 02:11:22
Пример плохой, так как отчество явно не является временным свойством.
Raphael 8.01.2018 14:12:24
@ Рафаэль Для меня пример полезен и, по крайней мере, объясняет концепцию. Не могли бы вы привести какой-нибудь лучший пример, если вы в курсе?
Chaklader Asfak Arefe 5.11.2018 10:27:11
@Yoda У нас может быть ссылка на NameFormatterподержанную машину toString(). Или что-нибудь еще, связанное с настройкой, просмотром или бизнес-логикой, а не с данными.
Raphael 5.11.2018 10:30:26

Мой маленький вклад:

Что такое переходное поле?
По сути, любое поле, измененное с помощью transientключевого слова, является временным полем.

Зачем нужны переходные поля в Java? Ключевое слово дает некоторый контроль над процессом сериализации и позволяет исключить некоторые свойства объектов из этого процесса. Процесс сериализации используется для сохранения Java-объектов, главным образом для того, чтобы их состояния могли сохраняться во время их передачи или неактивности. Иногда имеет смысл не сериализовать определенные атрибуты объекта. Какие поля следует пометить как переходные? Теперь мы знаем цель
transient


transientключевые слова и переходные поля, важно знать, какие поля помечать переходные. Статические поля также не сериализуются, поэтому соответствующее ключевое слово также поможет. Но это может испортить дизайн вашего класса; Вот где transientключевое слово приходит на помощь. Я стараюсь не допускать сериализации полей, значения которых могут быть получены из других, поэтому я отмечаю их как временные. Если у вас есть поле с именем interest, значение которого можно вычислить из других полей ( principal, rate& time), нет необходимости его сериализации.

Еще один хороший пример - количество слов в статье. Если вы сохраняете всю статью, вам не нужно сохранять количество слов, потому что оно может быть вычислено, когда статья будет «десериализована». Или подумайте о регистраторах;Logger экземпляры почти никогда не нужно сериализовать, поэтому их можно сделать временными.

36
21.08.2018 16:46:02
Ваше «простое предложение» - просто тавтология. Это ничего не объясняет. Тебе было бы лучше без этого.
user207421 1.07.2015 13:30:03
Это хорошее объяснение, где поле должно бытьtransient
Chaklader Asfak Arefe 5.11.2018 10:30:39
поле интереса и количество слов являются хорошими примерами переходных полей.
Tarun 18.01.2019 09:37:27
Еще один хороший пример использования: если у вашего объекта есть такие компоненты, как сокеты, и если вы хотите сериализовать, то что происходит с сокетом? Если бы это продолжалось, после десериализации, что бы держал сокет? Имеет смысл сделать этот объект сокета какtransient
Mohammed Siddiq 14.02.2019 22:55:11

Согласно переходному значению Google == длительность только в течение короткого времени; непостоянно.

Теперь, если вы хотите сделать что-то временное в Java, используйте ключевое слово transient.

Q: где использовать переходный процесс?

A: Как правило, в Java мы можем сохранять данные в файлы, собирая их в переменные и записывая эти переменные в файлы, этот процесс известен как сериализация. Теперь, если мы хотим избежать записи переменных данных в файл, мы бы сделали эту переменную переходной.

transient int result=10;

Примечание: временные переменные не могут быть локальными.

3
16.02.2019 10:18:50

Прежде чем ответить на этот вопрос, я должен объяснить вам СЕРИАЛИЗАЦИЮ , потому что, если вы понимаете, что означает сериализация в научном компьютере, вы легко поймете это ключевое слово.

Сериализация Когда объект передается по сети / сохраняется на физическом носителе (файл, ...), объект должен быть «сериализован». Сериализация преобразует байты серии объектов статуса. Эти байты отправляются в сеть / сохраняются, и объект воссоздается из этих байтов.
пример

public class Foo implements Serializable 
{
 private String attr1;
 private String attr2;
 ...
}

Теперь, ЕСЛИ ВЫ ХОТИТЕ НЕ ПЕРЕДАТЬ / СОХРАНИТЬ поле этого объекта ТАК , вы можете использовать ключевое слово transient

private transient attr2;

пример

7
23.05.2017 12:26:29

Проще говоря, временное ключевое слово 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;

   }
}
0
14.11.2017 13:40:27

Упрощенный пример кода для переходного ключевого слова.

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);
    }
}
0
5.06.2019 03:09:36

Поле, которое объявляется с помощью временного модификатора, не будет участвовать в сериализованном процессе. Когда объект сериализуется (сохраняется в любом состоянии), значения его переходных полей игнорируются в последовательном представлении, в то время как поле, отличное от переходных полей, будет участвовать в процессе сериализации. Это основная цель переходного ключевого слова.

0
24.01.2020 09:12:22