Odpowiedzi:
Słowo transient
kluczowe w Javie służy do wskazania, że pole nie powinno być częścią procesu serializacji (co oznacza zapisanie, jak w pliku).
Ze specyfikacji języka Java, Java SE 7 Edition , rozdział 8.3.1.3. transient
Pola :
Zmienne mogą być zaznaczone,
transient
aby wskazać, że nie są częścią trwałego stanu obiektu.
Na przykład, możesz mieć pola, które pochodzą z innych pól i powinieneś to zrobić tylko programowo, zamiast utrzymywania stanu przez serializację.
Oto GalleryImage
klasa, która zawiera obraz i miniaturę pochodzącą z obrazu:
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();
}
}
W tym przykładzie thumbnailImage
jest to obraz miniatury generowany przez wywołanie generateThumbnail
metody.
thumbnailImage
Pole jest oznaczone jako transient
, więc tylko oryginalna image
jest w odcinkach zamiast utrzymującej zarówno oryginalny obraz i obraz miniatury. Oznacza to, że potrzeba mniej pamięci do zapisania obiektu zserializowanego. (Oczywiście może to być lub nie być pożądane w zależności od wymagań systemu - to tylko przykład.)
W chwili deserializacji readObject
metoda jest wywoływana w celu wykonania wszelkich operacji niezbędnych do przywrócenia stanu obiektu z powrotem do stanu, w którym nastąpiła serializacja. W tym przypadku należy wygenerować miniaturę, więc readObject
metoda zostanie zastąpiona, aby miniaturka została wygenerowana przez wywołanie generateThumbnail
metody.
Aby uzyskać dodatkowe informacje, w artykule Poznaj sekrety interfejsu API Java Serialization API (który pierwotnie był dostępny w Sun Developer Network) znajduje się sekcja omawiająca użycie i przedstawiająca scenariusz, w którym transient
słowo kluczowe jest używane do zapobiegania serializacji niektórych pól.
Przed zrozumieniem transient
słowa kluczowego należy zrozumieć pojęcie serializacji. Jeśli czytelnik wie o serializacji, pomiń pierwszy punkt.
Serializacja to proces utrwalania stanu obiektu. Oznacza to, że stan obiektu jest konwertowany na strumień bajtów, który ma być używany do utrwalania (np. Przechowywania bajtów w pliku) lub przesyłania (np. Wysyłania bajtów przez sieć). W ten sam sposób możemy użyć deserializacji, aby przywrócić stan obiektu z bajtów. Jest to jedna z ważnych koncepcji w programowaniu Java, ponieważ serializacja jest najczęściej stosowana w programowaniu sieciowym. Obiekty, które muszą zostać przesłane przez sieć, muszą zostać przekonwertowane na bajty. W tym celu każda klasa lub interfejs musi implementować Serializable
interfejs. Jest to interfejs znaczników bez żadnych metod.
transient
słowo kluczowe i jakie jest jego przeznaczenie?Domyślnie wszystkie zmienne obiektu są przekształcane w stan trwały. W niektórych przypadkach możesz chcieć uniknąć utrwalania niektórych zmiennych, ponieważ nie musisz ich utrzymywać. Możesz więc zadeklarować te zmienne jako transient
. Jeśli zmienna zostanie zadeklarowana jako transient
, nie zostanie utrwalona. To jest główny cel tego transient
słowa kluczowego.
Chcę wyjaśnić powyższe dwa punkty następującym przykładem:
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);
}
}
A wynik będzie następujący:
First Name : Steve
Middle Name : null
Last Name : Jobs
Drugie imię jest zadeklarowane jako transient
, więc nie będzie przechowywane w pamięci trwałej.
NameFormatter
używanego do prowadzenia pojazdu toString()
. Lub cokolwiek innego związanego z konfiguracją, przeglądaniem lub logiką biznesową ... w przeciwieństwie do danych.
Aby umożliwić zdefiniowanie zmiennych, których nie chcesz serializować.
W obiekcie możesz mieć informacje, których nie chcesz serializować / utrwalać (być może odniesienie do nadrzędnego obiektu fabryki), a może serializacja nie ma sensu. Oznaczenie ich jako „przejściowych” oznacza, że mechanizm serializacji zignoruje te pola.
Mój mały wkład:
Co to jest pole przejściowe?
Zasadniczo każde pole zmodyfikowane transient
słowem kluczowym jest polem przejściowym.
Dlaczego pola przejściowe są potrzebne w Javie?
Słowo transient
kluczowe daje pewną kontrolę nad procesem serializacji i pozwala wykluczyć niektóre właściwości obiektu z tego procesu. Proces serializacji służy do utrwalania obiektów Java, głównie w celu zachowania ich stanów podczas przesyłania lub nieaktywności. Czasami sensowne jest, aby nie szeregować pewnych atrybutów obiektu.
Które pola należy oznaczyć jako przejściowe?
Teraz znamy celtransient
słowa kluczowego i pola przejściowe, ważne jest, aby wiedzieć, które pola oznaczyć jako przejściowe. Pola statyczne również nie są serializowane, więc odpowiednie słowo kluczowe również załatwi sprawę. Ale może to zrujnować twój projekt klasowy; tutaj transient
słowo kluczowe przychodzi na ratunek. Staram się nie dopuszczać serializacji pól, których wartości można wyprowadzić z innych, więc zaznaczam je jako przejściowe. Jeśli masz pole o nazwie, interest
którego wartość można obliczyć z innych pól ( principal
, rate
& time
), nie ma potrzeby serializowania go.
Innym dobrym przykładem jest liczenie słów w artykułach. Jeśli zapisujesz cały artykuł, naprawdę nie ma potrzeby zapisywania liczby słów, ponieważ można go obliczyć, gdy artykuł zostanie „zdezrializowany”. Lub pomyśl o rejestratorach;Logger
instancje prawie nigdy nie muszą być serializowane, dzięki czemu mogą stać się przejściowe.
transient
transient
transient
Zmienna jest zmienną, która nie może być w odcinkach.
Jednym z przykładów, kiedy może się to przydać, są zmienne, które mają sens tylko w kontekście konkretnej instancji obiektu i które stają się niepoprawne po serializacji i deserializacji obiektu. W takim przypadku przydatne jest, aby zmienne te stały się null
zamiast nich, aby w razie potrzeby można je ponownie zainicjować przydatnymi danymi.
transient
służy do wskazania, że pole klasy nie musi być serializowane. Prawdopodobnie najlepszym przykładem jest Thread
pole. Zwykle nie ma powodu, aby serializować a Thread
, ponieważ jego stan jest bardzo „specyficzny dla przepływu”.
A
odwołuje się do klasy, której nie można serializować B
(jak Thread
w twoim przykładzie), to A
albo zaznacz to odwołanie, ponieważ transient
XOR musi przesłonić domyślny proces serializacji, aby zrobić coś rozsądnego z B
XOR, zakładając, że tylko podklasy możliwe do serializacji B
są faktycznie przywoływane (więc rzeczywista podklasa musi dbać o swojego „złego” rodzica B
). XOR akceptuje, że serializacja się nie powiedzie. Tylko w jednym przypadku (oznaczonym jako przejściowy) B
jest automatycznie i cicho pomijany.
W systemach innych niż natywna Java można także użyć tego modyfikatora. Hibernacja, na przykład, nie utrwali pól oznaczonych @Transient lub modyfikatorem transient . Terakota również szanuje ten modyfikator.
Uważam, że symboliczne znaczenie modyfikatora brzmi: „to pole jest przeznaczone wyłącznie do użytku w pamięci. Nie utrwalaj go ani nie przenoś w żaden sposób poza tę konkretną maszynę wirtualną. Nie jest przenośny”. tzn. nie można polegać na jego wartości w innym obszarze pamięci maszyny wirtualnej. Podobnie jak niestabilna oznacza, że nie można polegać na pewnej pamięci i semantyce wątków.
transient
to nie byłoby słowo kluczowe, gdyby zostało zaprojektowane w tym czasie. Prawdopodobnie użyliby adnotacji.
Ponieważ nie wszystkie zmienne mają charakter szeregowalny
Zanim odpowiem na to pytanie, muszę wyjaśnić SERIALIZACJĘ , ponieważ jeśli rozumiesz, co to znaczy serializacja w komputerze naukowym, możesz łatwo zrozumieć to słowo kluczowe.
Serializacja
Gdy obiekt jest przesyłany przez sieć / zapisywany na nośniku fizycznym (plik, ...), obiekt musi zostać „zserializowany”. Serializacja konwertuje serie obiektów statusu bajtów. Te bajty są wysyłane do sieci / zapisywane, a obiekt jest ponownie tworzony z tych bajtów.
Przykład
public class Foo implements Serializable
{
private String attr1;
private String attr2;
...
}
Teraz, jeśli chcesz TO NIE TRANSFERT / Zapisane pola tego obiektu tak , można użyć słów kluczowych transient
private transient attr2;
Jest to potrzebne, gdy nie chcesz udostępniać poufnych danych związanych z serializacją.
Thread
(na przykład @AH), w którym to przypadku oznaczysz go jako przejściowy. Jednak wątek sam w sobie nie jest wrażliwymi danymi, po prostu nie ma logicznego sensu, aby go serializować (i nie można go serializować).
Zgodnie z Google przejściowe znaczenie == trwające tylko przez krótki czas; nietrwały.
Teraz, jeśli chcesz, aby cokolwiek było przejściowe w Javie, użyj przejściowego słowa kluczowego.
P: gdzie użyć przejściowego?
Odp .: Zasadniczo w Javie możemy zapisywać dane w plikach, gromadząc je w zmiennych i zapisując te zmienne w plikach, proces ten nazywany jest serializacją. Teraz, jeśli chcemy uniknąć zapisywania danych zmiennych do pliku, zmienilibyśmy tę zmienną jako przejściową.
transient int result=10;
Uwaga: zmienne przejściowe nie mogą być lokalne.
Mówiąc najprościej, słowo przejściowe java chroni pola przed serializacją, ponieważ ich pola nieprzemijające przeciwstawiają się części.
W tym fragmencie kodu nasza klasa abstrakcyjna implementuje interfejs Serializable BaseJob, rozszerzamy go z BaseJob, ale nie musimy serializować zdalnych i lokalnych źródeł danych; serializuj tylko pola nazwa_organizacji i 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;
}
}
Uproszczony przykładowy kod przejściowego słowa kluczowego.
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);
}
}
Pole zadeklarowane za pomocą przejściowego modyfikatora nie będzie brać udziału w procesie serializacji. Gdy obiekt jest szeregowany (zapisywany w dowolnym stanie), wartości jego pól przejściowych są ignorowane w reprezentacji szeregowej, podczas gdy pole inne niż pola przejściowe bierze udział w procesie serializacji. To jest główny cel przejściowego słowa kluczowego.
@DoNotSerialize
?