Co dokładnie oznacza, że klasa jest Serializable
w Javie? Lub ogólnie, jeśli o to chodzi ...
Co dokładnie oznacza, że klasa jest Serializable
w Javie? Lub ogólnie, jeśli o to chodzi ...
Odpowiedzi:
Serializacja polega na utrwalaniu obiektu z pamięci do sekwencji bitów, na przykład w celu zapisania na dysku. Deserializacja jest odwrotna - odczyt danych z dysku w celu uwodnienia / stworzenia obiektu.
W kontekście twojego pytania jest to interfejs, który po zaimplementowaniu w klasie ta klasa może być automatycznie serializowana i deserializowana przez różne serializatory.
Chociaż większość użytkowników już udzieliła odpowiedzi, ale chciałbym dodać przykład dla tych, którzy tego potrzebują, aby wyjaśnić pomysł:
Załóżmy, że masz osobę z klasy, taką jak ta:
public class Person implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
public String firstName;
public String lastName;
public int age;
public String address;
public void play() {
System.out.println(String.format(
"If I win, send me the trophy to this address: %s", address));
}
@Override
public String toString() {
return String.format(".....Person......\nFirst Name = %s\nLast Name = %s", firstName, lastName);
}
}
a następnie tworzysz taki obiekt:
Person william = new Person();
william.firstName = "William";
william.lastName = "Kinaan";
william.age = 26;
william.address = "Lisbon, Portugal";
Możesz serializować ten obiekt do wielu strumieni. Zrobię to dla dwóch strumieni:
Serializacja na standardowe wyjście:
public static void serializeToStandardOutput(Person person)
throws IOException {
OutputStream outStream = System.out;
ObjectOutputStream stdObjectOut = new ObjectOutputStream(outStream);
stdObjectOut.writeObject(person);
stdObjectOut.close();
outStream.close();
}
Serializacja do pliku:
public static void serializeToFile(Person person) throws IOException {
OutputStream outStream = new FileOutputStream("person.ser");
ObjectOutputStream fileObjectOut = new ObjectOutputStream(outStream);
fileObjectOut.writeObject(person);
fileObjectOut.close();
outStream.close();
}
Następnie:
Deserializacja z pliku:
public static void deserializeFromFile() throws IOException,
ClassNotFoundException {
InputStream inStream = new FileInputStream("person.ser");
ObjectInputStream fileObjectIn = new ObjectInputStream(inStream);
Person person = (Person) fileObjectIn.readObject();
System.out.println(person);
fileObjectIn.close();
inStream.close();
}
Oznacza to, że instancje klasy można przekształcić w strumień bajtów (na przykład w celu zapisania do pliku), a następnie ponownie przekształcić w klasy. To przeładowanie może nastąpić w innej instancji programu lub nawet na innym komputerze. Serializacja (w dowolnym języku) wiąże się jednak z różnego rodzaju problemami, zwłaszcza gdy masz odniesienia do innych obiektów w obrębie tego, który można serializować.
Oto szczegółowe wyjaśnienie serializacji : (mój własny blog)
Serializacja:
Serializacja to proces serializacji stanu obiektu, który jest reprezentowany i przechowywany w postaci sekwencji bajtów. Można to zapisać w pliku. Proces odczytywania stanu obiektu z pliku i przywracania go nazywa się deserializacją.
Jaka jest potrzeba serializacji?
We współczesnej architekturze zawsze istnieje potrzeba przechowywania stanu obiektu, a następnie jego pobierania. Na przykład w Hibernate, aby przechowywać obiekt, powinniśmy uczynić klasę Serializable. To, co robi, polega na tym, że po zapisaniu stanu obiektu w postaci bajtów można go przenieść do innego systemu, który może następnie odczytać stan i pobrać klasę. Stan obiektu może pochodzić z bazy danych lub innego pliku jvm lub z oddzielnego komponentu. Za pomocą serializacji możemy pobrać stan obiektu.
Kod Przykład i objaśnienie:
Najpierw spójrzmy na klasę przedmiotu:
public class Item implements Serializable{
/**
* This is the Serializable class
*/
private static final long serialVersionUID = 475918891428093041L;
private Long itemId;
private String itemName;
private transient Double itemCostPrice;
public Item(Long itemId, String itemName, Double itemCostPrice) {
super();
this.itemId = itemId;
this.itemName = itemName;
this.itemCostPrice = itemCostPrice;
}
public Long getItemId() {
return itemId;
}
@Override
public String toString() {
return "Item [itemId=" + itemId + ", itemName=" + itemName + ", itemCostPrice=" + itemCostPrice + "]";
}
public void setItemId(Long itemId) {
this.itemId = itemId;
}
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
public Double getItemCostPrice() {
return itemCostPrice;
}
public void setItemCostPrice(Double itemCostPrice) {
this.itemCostPrice = itemCostPrice;
}
}
W powyższym kodzie widać, że klasa Item implementuje Serializable .
To jest interfejs, który umożliwia serializację klasy.
Teraz widzimy, że zmienna o nazwie serialVersionUID jest inicjalizowana jako zmienna Long. Ta liczba jest obliczana przez kompilator na podstawie stanu klasy i atrybutów klasy. Jest to liczba, która pomoże jvm zidentyfikować stan obiektu, gdy odczytuje stan obiektu z pliku.
W tym celu możemy zajrzeć do oficjalnej dokumentacji Oracle:
Środowisko uruchomieniowe serializacji kojarzy z każdą możliwą do serializacji klasą numer wersji, zwany serialVersionUID, który jest używany podczas deserializacji w celu sprawdzenia, czy nadawca i odbiorca serializowanego obiektu załadowali klasy dla tego obiektu, które są zgodne pod względem serializacji. Jeśli odbiorca załadował klasę dla obiektu, który ma inny serialVersionUID niż klasa odpowiedniego nadawcy, deserializacja spowoduje wystąpienie InvalidClassException. Klasa możliwa do serializacji może jawnie zadeklarować swój własny serialVersionUID, deklarując pole o nazwie „serialVersionUID”, które musi być statyczne, final i typu long: ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L; Jeśli klasa możliwa do serializacji nie deklaruje jawnie serialVersionUID, następnie środowisko wykonawcze serializacji obliczy domyślną wartość serialVersionUID dla tej klasy na podstawie różnych aspektów tej klasy, zgodnie z opisem w specyfikacji serializacji obiektu Java (TM). Jednak zdecydowanie zaleca się, aby wszystkie możliwe do serializacji klasy jawnie deklarowały wartości serialVersionUID, ponieważ domyślne obliczenia serialVersionUID są bardzo wrażliwe na szczegóły klasy, które mogą się różnić w zależności od implementacji kompilatora i mogą w związku z tym spowodować nieoczekiwane InvalidClassExceptions podczas deserializacji. Dlatego, aby zagwarantować spójną wartość serialVersionUID w różnych implementacjach kompilatora Java, klasa możliwa do serializacji musi zadeklarować jawną wartość serialVersionUID. Zaleca się również, aby jawne deklaracje serialVersionUID używały prywatnego modyfikatora, jeśli to możliwe,
Jeśli zauważyłeś, istnieje inne słowo kluczowe, którego użyliśmy, które jest przejściowe .
Jeśli pola nie można serializować, należy je oznaczyć jako przejściowe. Tutaj oznaczyliśmy itemCostPrice jako przejściowy i nie chcemy, aby był zapisywany w pliku
Przyjrzyjmy się teraz, jak zapisać stan obiektu w pliku, a następnie odczytać go stamtąd.
public class SerializationExample {
public static void main(String[] args){
serialize();
deserialize();
}
public static void serialize(){
Item item = new Item(1L,"Pen", 12.55);
System.out.println("Before Serialization" + item);
FileOutputStream fileOut;
try {
fileOut = new FileOutputStream("/tmp/item.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(item);
out.close();
fileOut.close();
System.out.println("Serialized data is saved in /tmp/item.ser");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void deserialize(){
Item item;
try {
FileInputStream fileIn = new FileInputStream("/tmp/item.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
item = (Item) in.readObject();
System.out.println("Serialized data is read from /tmp/item.ser");
System.out.println("After Deserialization" + item);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Na powyższym możemy zobaczyć przykład serializacji i deserializacji obiektu.
W tym celu użyliśmy dwóch klas. Do serializacji obiektu użyliśmy ObjectOutputStream. Do zapisania obiektu w pliku wykorzystaliśmy metodę writeObject.
Do deserializacji użyliśmy ObjectInputStream, który odczytuje obiekt z pliku. Używa readObject do odczytu danych obiektu z pliku.
Wynik powyższego kodu wyglądałby następująco:
Before SerializationItem [itemId=1, itemName=Pen, itemCostPrice=12.55]
Serialized data is saved in /tmp/item.ser
After DeserializationItem [itemId=1, itemName=Pen, itemCostPrice=null]
Zwróć uwagę, że itemCostPrice z deserializowanego obiektu ma wartość null, ponieważ nie został zapisany.
Serializacja obejmuje zapisanie bieżącego stanu obiektu do strumienia i przywrócenie równoważnego obiektu z tego strumienia. Strumień działa jako kontener dla obiektu
Serializable jest wywoływany jak interfejs, ale bardziej przypomina flagę podsystemu serializacji w czasie wykonywania. Mówi, że ten obiekt można uratować. Wszystkie zmienne instancji Objects, z wyjątkiem żadnych obiektów, które można serializować, i tych oznaczonych jako ulotne, zostaną zapisane.
Wyobraź sobie, że Twoja aplikacja może zmienić kolor jako opcję, bez pozostawiania tego ustawienia na zewnątrz, musisz zmieniać kolor za każdym razem, gdy ją uruchomisz.
Serializacja to technika przechowywania lub zapisywania obiektów i danych w plikach. Używając ObjectOutputStream
i FileOutputStream
klas. Te klasy mają swoje specyficzne metody utrwalania obiektów. lubićwriteObject();
dla jasnego wyjaśnienia za pomocą liczb. Zobacz tutaj, aby uzyskać więcej informacji
Przedstawić z innej perspektywy. Serializacja to rodzaj interfejsu zwanego „interfejsem znaczników”. Interfejs znacznika to interfejs, który nie zawiera deklaracji metod, a jedynie wyznacza (lub „zaznacza”) klasę, która implementuje interfejs jako mający jakąś właściwość. Jeśli rozumiesz polimorfizm, będzie to miało sens. W przypadku interfejsu znacznika Serializable metoda ObjectOutputStream.write (Object) nie powiedzie się, jeśli jej argument nie implementuje interfejsu. To jest potencjalny błąd w Javie, mógł to być ObjectOutputStream.write (Serializable)
Bardzo zalecane: przeczytanie pozycji 37 z książki Effective Java autorstwa Joshua Blocha, aby dowiedzieć się więcej.
Serializacja: zapis stanu obiektu do pliku / sieci lub gdziekolwiek. (Średni formularz obsługiwanego obiektu Java do formularza obsługiwanego pliku lub formularza obsługiwanego przez sieć)
Deserializacja: odczyt stanu obiektu z pliku / sieci lub z dowolnego miejsca. (Średni plik / format obsługiwany przez sieć do formularza obsługiwanego przez obiekt Java)
Wystarczy dodać do innych odpowiedzi i w odniesieniu do ogólności. Serializacja jest czasami nazywana archiwizacją, na przykład w Objective-C.
Serializable
:Serializability of a class is enabled by the class implementing the java.io.Serializable interface. Classes that do not implement this interface will not have any of their state serialized or deserialized. All subtypes of a serializable class are themselves serializable. The serialization interface has no methods or fields and serves only to identify the semantics of being serializable.