java Serializable interface has no function, why it affects "writeObject"/"readObject" - java

I checked that the interface of
Serializable
Has no function definition, yet when I define
private void readObject(ObjectOutputStream oos){
System.out.println("readObject!!");
}
private void writeObject(ObjectOutputStream oos){
System.out.println("writeObject!!");
}
function in a class, they're called while object is being serialized.
This is odd to me, if the interface defines these 2 functions, then I should override them to make sure they're called.
But in Serializable, how does compiler generate code that if I define my own "writeObject"/"readObject", they're called while serialization?
I tried to append
#Override
annotation on top of both functions, compiler reports error.
So how it works at all, would you help to give some explanations?
Thanks a lot!

java.io.Serializable is a functional interface, so that means it doesn't define any methods in it. #Override annotation is put if only you really wanna make sure noone will try to modify your overridden method. The reason you got a compiler error on #Override is that there is no such method in Serializable, but instead you can find them in ObjectInputStream and ObjectOutputStream (which use as a low-level classes FileInputStream and FileOutputStream respectively).
If you really wanna do Serialization on let's say, a list, you can do it like this:
package Chaper8.IO;
import java.io.*;
import java.util.*;
public class Serialization_Deserialization {
public static void main(String [] args){
/*
* try-catch with resources, JVM makes sure to close the resources after you've finished using it
* much easier than using finally and getting an exception for each resource closed
*
*/
try(FileOutputStream out = new FileOutputStream("C:\\Users\\Andrei\\Desktop\\Exemple\\worker.txt");
ObjectOutputStream oos = new ObjectOutputStream(out);
FileInputStream in = new FileInputStream("C:\\Users\\Andrei\\Desktop\\Exemple\\worker.txt");
ObjectInputStream ois = new ObjectInputStream(in);){
//instances of the Worker class
Worker w1 = new Worker("Worker1", 123456 , 2000.5);
Worker w2 = new Worker("Worker2", 765436, 1500.15);
Worker w3 = new Worker("Worker3", 364582, 1700.45);
Worker w4 = new Worker("Worker4", 878234, 2100.34);
ArrayList<Worker> list = new ArrayList<>();
//just adding the persons in the list
list.add(w1);
list.add(w2);
list.add(w3);
list.add(w4);
System.out.println("Doing serialization");
oos.writeObject(list);
System.out.println("Doing deserialization");
ois.readObject();
}catch(IOException | ClassNotFoundException e){
e.printStackTrace();
}
}
}
Worker.java
/*
* Worker class, basic type with variables, constructor, and toString() overridden
* Here I have implemented Serializable for the reason that I need to make sure that
* I will serialize the object within the class
*
* Note that I used transient for id. transient is a special keyword which makes sure
* that id will not be serialized, used for security reasons.
*
* serialVersionUID is another variable which is used during deserialization
* to verify that the sender and receiver of a serialized object have loaded
* classes for that object that are compatible with respect to serialization.
* Throws InvalidClassException if the object has a different serialVersionUID
* than that of the corresponding sender's class.
*
*/
import java.io.*;
class Worker implements Serializable{
private static final long serialVersionUID = 1L;
private String name;
private transient int id;
private double wage;
public Worker(String name, int id, double wage){
this.name = name;
this.id = id;
this.wage = wage;
}
public String toString(){
return "Person with name " +
name + " and with id " +
id + " has a salary of " + wage + "$";
}
}

Related

How to save and load a class that contains a list of another class?

I had a class Inventory that contains a list of Treasure class. I designed the Reader to read the Inventory as a list of Treasure, but when I want to call the reader from my main function, it says that Inventory is not the same as a list of Treasure. And now I don't know what should I do, should I change the read method to only read Inventory, but then again Inventory contains all the list of Treasure that I need. I am very lost as how to do it.
public class Inventory implements SavedGames {
private ArrayList<Treasure> inventory;
private static Inventory instance;
// EFFECTS: constructs an empty player inventory
private Inventory() {
this.inventory = new ArrayList<Treasure>();
inventory.add(new Treasure("Potion", 4));
}
private void loadGames() {
try {
MainCharacter character = Reader.readCharacter(new File(CHARACTER_FILE));
Monster monster = Reader.readMonster(new File(MONSTER_FILE));
List<Treasure> inventory = Reader.readInventory(new File(INVENTORY_FILE));
this.character = character;
this.monster = monster;
this.inventory = inventory;
} catch (IOException e) {
System.out.println("Unable to read files, resetting...");
startApp();
}
}
private static List<Treasure> parseInventory(List<String> fileContent) {
List<Treasure> inventory = new ArrayList<>();
for (String line : fileContent) {
ArrayList<String> lineComponents = splitString(line);
inventory.add(parseTreasure(lineComponents));
}
return inventory;
}
private static Treasure parseTreasure(List<String> components) {
String description = components.get(0);
int amount = Integer.parseInt(components.get(1));
return new Treasure(description, amount);
}
}
Serialization is a mechanism of converting the state of an object into a byte stream. Deserialization is the reverse process where the byte stream is used to recreate the actual Java object in memory. This mechanism is used to persist the object.
The byte stream created is platform independent. So, the object serialized on one platform can be deserialized on a different platform.
To make a Java object serializable we implement the java.io.Serializable interface.
The ObjectOutputStream class contains writeObject() method for serializing an Object.
public final void writeObject(Object obj)
throws IOException
The ObjectInputStream class contains readObject() method for deserializing an object.
public final Object readObject()
throws IOException,
ClassNotFoundException

Understanding singletons class in Java

When reading Effective Java I found that the most useful approach to implement singletons is just using enums with single INSTANCE. But in case we need to make it a class, according to some of his susggestions the perfect serializable thread-safe singleton class would look like this:
public class SerializableSingletonClass implements Serializable{
private static final long serialVersionUID = 1L;
private int value;
private String name;
private SerializableSingletonClass(int value, String name) {
if( value < 0 ) throw new IllegalArgumentException("Value may not be less than 0");
this.value = value;
this.name = Validate.notNull(name, "Name may not be null");
}
private static class SerializableSingletonHolder{
public static final SerializableSingletonClass INSTANCE;
static {
INSTANCE = new SerializableSingletonClass(0, "default");
}
}
private void readObject(ObjectInputStream stream) throws InvalidObjectException{
throw new InvalidObjectException("proxy required");
}
private Object writeReplace(){
return new SerializationProxy(this);
}
private static class SerializationProxy implements Serializable{
private static final long serialVersionUID = 1L;
public SerializationProxy(SerializableSingletonClass ignored) { } //Here is the question
private Object readResolve(){
return SerializableSingletonHolder.INSTANCE;
}
}
}
As far as I got he proposed to just replace serialized instances with one that's used currently.
So, why do we ever need to make singletons serializable in the owing that their serial form would not be ever used. We just throw it out and replace deserialized instance with the current one.
To me the problem of implementing serializable singletons looks like only a theoretical one. Accoring to what I said, deserializing singleton doesn't make much sense (in the case of enums either).
So what did I miss? Couldn't you explain it in a bit more detail?
enums are also serializable, just not their fields.
I think it's important to keep it simple and easy to maintain e.g. use a text file if you are going to save it.
I would add a method like save and load to it (possibly with a filename)
enum SaveableSingleton {
INSTANCE;
String name;
int value;
public void load(String filename) throws IOException {
try (Scanner scanner = new Scanner(new File(filename))) {
name = scanner.nexLine();
value = scanner.nextInt();
}
}
public void save(String filename) throws IOException {
try (PrintWriter pw = new PrintWriter(new File(filename))) {
pw.println(name);
pw.println(value);
}
}
}
creates a file like
my-name-is
12345
If you have some field in some other serializable class where you store this singleton instance and want to serialize / deserialize that class, you would always have to mark that field transient and make sure to fill it manually on deserialization. If you handle it in the Singleton, you don't have to do this. I guess that is the reason for a serializable singleton.

javafx: How to write the writeObject() and readObject() for this object?

I have a Trade object with the code below and it implements the Serializable interface but since it contains javafx properties , I get this java.io.NotSerializableException and hence failed to properly do writeObject() and readObject(). My ultimate goal is to be able to write and read this object using ObjectOutputStream and ObjectInputStream
I read the 3 links:
NotSerializableException on SimpleListProperty
Oracle doc
Java Custom Serialization
Since my Trade class is running a ScheduledService to pick up the closing price from Google Finance, I know that I need to call startService() within the readObject() to ensure that when the readObject() method is called and the object is deserialized, the thread will restart again.
Furthermore, I understand that I need to I need to define these 2 private methods within my Trade Class.
private void writeObject(ObjectOutputStream out) throws IOException
{
out.defaultWriteObject();
// What else should I write in here?
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
{
// our "pseudo-constructor"
in.defaultReadObject();
// Not sure what else I need to write in here
// now we are a "live" object again, so let's run rebuild and start
startService();
}
Question: I have read the 3rd link above and I am still confused about what else should go into these two private methods above ?
Because my trade object has quite a lot of properties, but all it really needs
are just buySell,transactionDate,symbol, double volume, double price to construct an object. Should I set the rest of the properties to transient then?
public class Trade implements Serializable{
// properties
private Long creationTime;
private int counter;
private ObjectProperty<LocalDate> transactionDate;
private StringProperty symbol;
private StringProperty details;
private StringProperty buySell;
private DoubleProperty volume;
private DoubleProperty price;
private ReadOnlyDoubleWrapper transactionFee;
private final ReadOnlyDoubleWrapper closingPrice;
private final PauseTransition delay;
private ReadOnlyBooleanWrapper caution;
private final ScheduledService<webScraping> stockService = new ScheduledService<webScraping>() {
// web scrape google finance data
...
}
// constructor
public Trade(BuySell buySell, LocalDate transactionDate, String symbol, double volume, double price){
...
startService();
creationTime = Calendar.getInstance().getTimeInMillis();
}
// getters and setters and instance methods that return the properties themselves
public Long getCreationTime(){
return this.creationTime;
}
private Object writeReplace() {
return new TradeProxy(this);
}
private void readObject(ObjectInputStream stream)
throws InvalidObjectException {
throw new InvalidObjectException("Proxy required");
}
...
private static class TradeProxy implements Serializable{
private String buySell;
private LocalDate transactionDate;
private String stockTicker;
private double price;
private double volume;
private Long creationTime;
private TradeProxy(Trade trade){
this.buySell = trade.getBuySell();
this.transactionDate = trade.getTransactionDate();
this.stockTicker = trade.getStockTicker();
this.price = trade.getPrice();
this.volume = trade.getVolume();
this.creationTime = trade.getCreationTime();
}
private void writeObject(ObjectOutputStream s ) throws IOException{
s.defaultWriteObject();
}
private Object readResolve() throws ObjectStreamException{
return new Trade(this.buySell,this.transactionDate, this.symbol, this.volume, this.price);
}
}
}
UPDATE: I have updated my code. But since creationTime is not an argument of the Trade's constructor, I do not know how to serialize/deserialize it in my case. To be more precise, if I create a Trade object at time say creationTime = 1443444301488, I want this object be serialized and when I read in the object and deserialize it, I want to the creationTime to be exactly the same as what it was (i.e. 1443444301488) and I don't know how to achieve this. This is the problem that I am facing now.
I would avoid serializing javafx objects. Instead create a javabean object that contains the state that should be serialized. Then you can have your Trade object build itself from the serialized proxy javabean.
class TradeSerialProxy {
private String simpleBeanFields;
private int moreSimpleStateFields;
//getters and setters
}
then
public Trade (TradeSerialProxy proxy) {
//build the Trade object using the proxy.
}
You see something similar to this in the Effective Java book. Though in that book he uses proxies for security purposes. The rule I follow is to only serialize simple javabean objects and that's that. Avoid serializing complicated objects.
Also, if you use regular Java serialization, then you might run into version problems whenever your class implementation changes. There are ways around this, like using JSON and GSON for serialization. Because I was using pure standard Java, and no external libs/jars, I had to accomplish this with HashMap... where I would only serialize the HashMap and have the real objects build themselves using a HashMap passed to it. I had to do this to avoid getting the constant serial version mismatch exception and sticking to pure standard vanilla Java.
EDIT: This is an object that uses serialization proxy pattern. This apporach is from Effective Java 2nd Edition item 78.
public class UserProfile implements Serializable {
///////////////////////////////////////////////////////////////////////////
//private variables
private String profileName = null;
private int version = 0;
private LeaderboardPermissions leaderboardState = LeaderboardPermissions.ASK;
private boolean upgradeWalkThrough = true;
private final Map<GameType, GameTypeStats> gameTypeStats;
private final String id;
private boolean offNet = true;
///////////////////////////////////////////////////////////////////////////
//serialization stuff
private static final long serialVersionUID = 7625672295622776890L;
private UserProfile(UserProfileProxy t) {
this.profileName = t.profileName;
this.version = t.version;
this.leaderboardState = t.leaderboardState;
this.upgradeWalkThrough = t.upgradeWalkThrough;
this.gameTypeStats = t.gameTypeStats;
this.id = t.id;
this.offNet = t.offNet;
}
private Object writeReplace() {
return new UserProfileProxy(this);
}
private void readObject(ObjectInputStream stream)
throws InvalidObjectException {
throw new InvalidObjectException("Proxy required");
}
///////////////////////////////
//serialization proxy
private static class UserProfileProxy implements Serializable {
private String profileName = null;
private int version = 0;
private final LeaderboardPermissions leaderboardState;
private boolean upgradeWalkThrough = true;
private final Map<GameType, GameTypeStats> gameTypeStats;
private String id;
private static final long serialVersionUID = 6985672045622776890L;
private boolean offNet;
private UserProfileProxy(UserProfile t) {
this.profileName = t.profileName;
this.version = t.version;
this.leaderboardState = t.leaderboardState;
this.upgradeWalkThrough = t.upgradeWalkThrough;
this.gameTypeStats = t.gameTypeStats;
this.id = t.id;
this.offNet = t.offNet;
}
private void writeObject(ObjectOutputStream s) throws IOException {
s.defaultWriteObject();
}
private Object readResolve() throws ObjectStreamException {
return new UserProfile(this);
}
}
This approach is baked into Java object serialization protocol. Another method I am using now utilizes a HashMap<String, Object> as the proxy.
Here is the interface. I had to have the methods in this interface return their hash because my extensive use of encrypting the serialized object's hashes to prevent tampering with the saved files. I'm not necessarily recommending this but showing possibilities of serialization proxies.
public interface MapSerializable {
public static String CLASS_KEY = "MapSerializable.CLASS_KEY";
/**
* Object will populate a HashMap of objects that it can use at some later
* point to reinitialize itself. Return the hash of the objects used to
* build itself.
*
* #param serial
* #return
* #throws IOException
*/
public int populateSerialMap(HashMap<String, Object> serial) throws IOException;
/**
* Object will initialize itself using the input HashMap. Returns the hash
* of the objects that were used to initialize itself from the Map.
*
* #param serial
* #return hash of the objects that were used to load yourself.
* #throws IOException
*/
public int initializeFromMap(HashMap<String, Object> serial) throws IOException;
}
And here is an example of an object using it.
public class GameType implements MapSerializable {
////////////////////////////////////////////////////////////////////////////
//private variables
private String displayName = null;
////////////////////////////////////////////////////////////////////////////
//constrcutor
public GameType(String name) {
this.displayName = name;
}
GameType() {
}
////////////////////////////////////////////////////////////////////////////
//public methods
#Override
public int populateSerialMap(HashMap<String, Object> serial) throws IOException {
serial.put("displayName", displayName);
return 17 * Objects.hashCode(displayName);
}
#Override
public final int initializeFromMap(HashMap<String, Object> serial) throws IOException {
int hash = 0;
ObjectHashPair<String> ohp = model.utils.SerialUtils.getObjectFromMap(serial, "displayName", "");
displayName = ohp.obj;
hash += 17 * ohp.hash;
return hash;
}
}
EDIT2: Deeper explanation into the first method.
You need to first understand some of the basics of Java serialization. Java does most of the heavy lifting for you, it actually has a writeObject and readObject that work just fine for most cases. This is good news for you since all you need to do is deciding what fields need to go into the proxy just the things you want to serialize (the state) and not have to worry about actually doing the serialization (adding/removing objects to the stream). Next, you need to be able to initialize your main class using the proxy and vice versa. So create a constructor in your main class that takes a proxy object as input, in that constructor initialize your main class. Do the same for the proxy object. Lastly, Java even gives you the ability to use a proxy for writing and reading via the writeReplace and readResource methods. The writeReplace for the main class will return an instance of the proxy, essentially telling Java to serialize that object instead. On the flip side in the proxy you'll need a readResolve to return an instance of the main object during deserialization.
SO lets go through the steps in a bullet list:
1) Decide what fields need saving and create your proxy class (I used an inner nested class) to have those fields.
2) Create the constructors in main and proxy class. Main(Proxy obj) and Proxy(Main obj).
3) Implement the writeReplace and readResolve on the main and proxy classes, respectively.
I hope that helps.

Java OOP with serialization, file is not being loaded

I am trying to create a form where the user saves three pieces of information (id, name and surname). The following is the code of the person:
public class Person implements Serializable {
private String Personfirstname;
private String Personlastname;
private String PersonID;
/**
* #return the Personfirstname
*/
public String getPersonfirstname() {
return Personfirstname;
}
/**
* #param Personfirstname the Personfirstname to set
*/
public void setPersonfirstname(String Personfirstname) {
this.Personfirstname = Personfirstname;
}
/**
* #return the Personlastname
*/
public String getPersonlastname() {
return Personlastname;
}
/**
* #param Personlastname the Personlastname to set
*/
public void setPersonlastname(String Personlastname) {
this.Personlastname = Personlastname;
}
/**
* #return the PersonID
*/
public String getPersonID() {
return PersonID;
}
/**
* #param PersonID the PersonID to set
*/
public void setPersonID(String PersonID) {
this.PersonID = PersonID;
}
public void savecons()
{
try {
File selectedFile = new File("Consultant - " + PersonID + ".txt");
FileOutputStream fileStream = new FileOutputStream(selectedFile);
ObjectOutputStream oos = new ObjectOutputStream(fileStream);
oos.writeObject(this);
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
private String toString(int ConsultantID) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
public static Person loadcons() throws Exception
{
Person loadcons = null;
JFileChooser chooser = new JFileChooser();
int chooserOption = chooser.showSaveDialog(null);
chooserOption = JFileChooser.APPROVE_OPTION;
try {
File file = new File (chooser.getSelectedFile().getAbsolutePath());
ObjectInputStream input = new ObjectInputStream(new FileInputStream(file));
loadcons = (Person) input.readObject();
input.close();
return loadcons;
} catch (IOException ex) {
System.out.println(ex.getMessage());
} catch (ClassNotFoundException ex) {
System.out.println(ex.getMessage());
}
throw new Exception("No files were selected");
}
private String toString(String PersonID) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
The code have the 3 variables and 2 methods. One of the methods saves the variable information into a text files (the text files is being outputted but I am not sure if the information is getting into it as its all symbols. The other method is a load button that will import the data back in the fields.
Then I created a form with the following code. There the saving is:
Person cons_save = new Person();
cons_save.setPersonfirstname(this.jTextField1.getText());
cons_save.setPersonlastname(this.jTextField2.getText());
cons_save.setPersonID(this.jTextField3.getText());
this.jTextField1.setText("");
this.jTextField2.setText("");
this.jTextField3.setText("");
cons_save.savecons();
and the loading is the below:
Person cons_load = Person.loadcons();
this.jTextField1.setText(cons_load.getPersonfirstname());
this.jTextField2.setText(cons_load.getPersonlastname());
this.jTextField3.setText(cons_load.getPersonID());
When I press the loading button it doesn't work as it needs an exception but when I create the exception the button works but when I chose the file, the information is not going to the fields.
Person cons_load;
try {
cons_load = Person.loadcons();
this.jTextField1.setText(cons_load.getPersonfirstname());
this.jTextField2.setText(cons_load.getPersonlastname());
this.jTextField3.setText(cons_load.getPersonID());
} catch (Exception ex) {
Logger.getLogger(CreateConsultant.class.getName()).log(Level.SEVERE, null, ex);
}
I appreciate every help I can get as this is the first time I am trying to program in java oop.
You will need to mark the classes you want to save to file with the Serializable interface. This should allow the serialization of the objects you are after.
As per the JavaDoc (I highlighted some text in bold):
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.
Essentially, this: public class Person needs to become this: public class Person implements Serializable { static final long serialVersionUID = ....
It is important that serialVersionUID is unique for each class since it is used for serialization and deserialization purposes.
EDIT: As per the comments below, I copied your code and ran it. I managed to save and read it back without issues. The code ran as is in your question, seeing that you have added the marker interface (it is good practice to also include your serialVersionUID field).
I then removed the implements Serializable section of your code, and I got this error: writing aborted; java.io.NotSerializableException: so.Person. This essentially shows that you are trying to store a non serializable item.
Below is what the content of the file looks like when the exception is thrown:

Are static variables serialized in Serialization process

I'm stumbled upon understanding java serialization. I have read in many documents and books that static and transient variables cannot be serialized in Java.
We declare a serialVersionUid as follows.
private static final long serialVersionUID = 1L;
If a static variable was not serialized then, we often face an exception during the de-serialization process.
java.io.InvalidClassException
in which the serialVersionUID from the deserialized object is extracted and compared with the serialVersionUID of the loaded class.
To my knowledge i think that if static variables cannot be serialized. There is no point of that exception. I may be wrong because I'm still learning.
Is it a myth that "Static and transient variables in java cannot be serialized". Please correct me, I'm in a mess about this concept.
Instance Variables: These variables are serialized, so during deserialization we will get back the serialized state.
Static Variables: These variables are not serialized, So during deserialization static variable value will loaded from the class.(Current value will be loaded.)
transient Variables: transient variables are not serialized, so during deserialization those variables will be initialized with corresponding default values (ex: for objects null, int 0).
Super class variables: If super class also implemented Serializable interface then those variables will be serialized, otherwise it won't serialize the super class variables. and while deserializing, JVM will run default constructor in super class and populates the default values. Same thing will happen for all superclasses.
serialVersionUID is a special static variable used by the serialization and deserialization process, to verify that a local class is compatible with the class used to serialize an object. It's not just a static variable as others, which are definitely not serialized.
When an object of a class is first serialized, a class descriptor containing among other things the class name and serial version UID is written to the stream. When this is deserialized, the JVM checks if the serial version UID read from the stream is the same as the one of the local class. If they're not, it doesn't even try to deserialize the object, because it knows the classes are incompatible.
serialVersionUID is special and is not subject to these rules. There is code within the serialization machinery that specifically handles this field to perform the automatic version checks.
The serialVersionUID is also serialized in this case.
Any static variable that is provided a value during class initialization is serialized.
However in normal cases, where you would provide the value to a static variable at the main class / run-time would not be serialized.
You can try to access the serialVersionUID by making it public and try to access it after deserialization.
You can refer "http://javabeginnerstutorial.com/core-java-tutorial/transient-vs-static-variable-java/" for more information.
Hope that helps. Cheers !!
You can test this for yourself - here's some example code that should answer your question:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class TestJava implements Serializable{
public static int k = 10;
public int j = 5;
public static void main(String[] args) {
TestJava tj1= new TestJava();
TestJava tj2;
try{ //serialization
FileOutputStream fos = new FileOutputStream("myclass.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(tj1);
oos.close();
fos.close();
System.out.println("object serielized 1..."+tj1.j);
System.out.println("object serielized 2..."+tj1.k);
System.out.println("object serielized 3..."+k);
k=++k; // 'k' value incrementd after serialization
} catch(FileNotFoundException fnfe){
fnfe.printStackTrace();
} catch(IOException ioex){
ioex.printStackTrace();
}
try{ //deserialization
FileInputStream fis = new FileInputStream("myclass.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
tj2 = (TestJava) ois.readObject();
ois.close();
fis.close();
System.out.println("object DEEEEserielized 1..."+tj2.j);
System.out.println("object DEEEEserielized 2..."+tj2.k);
System.out.println("object DEEEEserielized 3..."+k);
// in deserialization 'k' value is shown as incremented.
// That means Static varialbe 'K' is not serialized.
// if 'K' value is serialized then, it has to show old value before incrementd the 'K' value.
} catch(FileNotFoundException fnfe){
fnfe.printStackTrace();
} catch(IOException ioex){
ioex.printStackTrace();
} catch(ClassNotFoundException CNFE){
CNFE.printStackTrace();
}
}
}
This will output the following:
object serielized 1...5
object serielized 2...10
object serielized 3...10
object DEEEEserielized 1...5
object DEEEEserielized 2...11
object DEEEEserielized 3...11
So we create an object of class TestJava with one static integer field and one non-static field. We serialize the object, then - after serialization - increment the static integer.
When we later deserialize the object, we see that it has the incremented value, implying that it was not serialized.
Below example explains about static ,instance,transient and super class varialbes serialization and their outputs.
Serializing class:
public class SerializeEx extends SuperSerializeEx implements Serializable {
private static final long serialVersionUID = 1L;
public static int staticNumber = 1234;
public int instanceNumber = 1234;
public SerializeEx() {
staticNumber = 0;
instanceNumber = 0;
System.out.println("---sub class constructor---");
}
public SerializeEx(int staticNumber, int instanceNumber, int superNumber) {
super(superNumber);
this.staticNumber = staticNumber;
this.instanceNumber = instanceNumber;
}
}
Super Class:
public class SuperSerializeEx {
public int superNumber;
public SuperSerializeEx() {
System.out.println("---super class constructor---");
this.superNumber = 1000;
}
public SuperSerializeEx(int superNumber) {
this.superNumber = superNumber;
}
}
Serialization & Deserialization:
public class MainSerialization {
public static void main(String[] args) {
String fileName = "testing.txt";
serialize(fileName);
deSerialize(fileName);
}
public static void serialize(String fileName) {
System.err.println("Serialize.....");
SerializeEx serializeMe = new SerializeEx(10, 10, 10);
FileOutputStream fos = null;
ObjectOutputStream out = null;
try {
fos = new FileOutputStream(fileName);
out = new ObjectOutputStream(fos);
out.writeObject(serializeMe);
out.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static void deSerialize(String fileName) {
System.err.println("DeSerialize.....");
SerializeEx time = null;
FileInputStream fis = null;
ObjectInputStream in = null;
try {
fis = new FileInputStream(fileName);
in = new ObjectInputStream(fis);
time = (SerializeEx) in.readObject();
in.close();
} catch (IOException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
System.err.println("Instance Numer = " + time.instanceNumber + " \tStatic Number= " + time.staticNumber + " \t Super Number= " + time.superNumber);
SerializeEx serializeMe = new SerializeEx(1001, 1001, 1001); //Modifying the static and instnce variables
System.err.println("Instance Numer = " + time.instanceNumber + " \tStatic Number= " + time.staticNumber + " \t Super Number= " + time.superNumber);
}
}
Output:
---super class constructor---
Serialize.....
DeSerialize.....
Instance Numer = 10 Static Number= 10 Super Number= 1000
Instance Numer = 10 Static Number= 1001 Super Number= 1000
No, if a class have static variable then at the time of serialization that variable will be skipped . because static variable is unique for all object and serialization is used for only save the object properties ( state of object ).
static variable is a property of class
Yes, static variable will be serialized if it is initialized at the time of declaration.
For example,
case 1 : without initialization at the time of declaration
class Person implements Serializable{
public String firstName;
static String lastName;
}
public class Employee {
public static void main(String[] args) {
Person p = new Person();
p.firstName="abc";
p.lastName="xyz";
//to do serialization
}
}
output :
//after deserialization
firstName= abc
lastName= null
case 2 : with initialization at the time of declaration
class Person implements Serializable{
public String firstName=="abc";
static String lastName="pqr";
}
public class Employee {
public static void main(String[] args) {
Person p = new Person();
p.firstName="abc";
p.lastName="xyz";
//to do serialization
}
}
output :
//after deserialization
firstName= abc
lastName= pqr
Any static variable which has been initialised at the time of declaration will be serialized.

Categories