I am trying to serialize this arraylist:
static ArrayList<Product> Chart=new ArrayList<Product>();
with these objects:
double Total;
String name;
double quantity;
String unit;
double ProductPrice
This is the class so far:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Product implements Serializable{
double Total;
String name;
double quantity;
String unit;
double ProductPrice;
public Product(String n)
{
name=n;
}
private void writeObject(ObjectOutputStream s) throws IOException
{
s.defaultWriteObject();
Product pt=new Product(name);
ObjectOutputStream oos=new ObjectOutputStream(s);
oos.writeObject(pt);
}
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException
{
s.defaultReadObject();
Product pt;
ObjectInputStream ios =new ObjectInputStream(s);
ObjectInputStream ois = null;
pt=(Product)ois.readObject();
}
}
I am trying to serialize and deserialize the arraylist(declared in another class) so that the objects in the arraylist will be saved between runtimes. Any ideas?
Why are you creating new Product objects in these methods? They are not static, so I would assume they should operate on this? You also are trying to call readObject() on an Object you just set to null.
If you can give some more details about the errors you're seeing and how you're using this, we can probably help more.
Edit: Added some sample code
Write it out:
Product p = new Product("My Product");
try
{
FileOutputStream fileOut =
new FileOutputStream("product.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(p);
out.close();
fileOut.close();
} catch(IOException ioe)
{
ioe.printStackTrace();
}
Read it in:
Product p = null;
try
{
FileInputStream fileIn = new FileInputStream("product.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
p = (Product) in.readObject();
in.close();
fileIn.close();
} catch(IOException ioe)
{
ioe.printStackTrace();
return;
} catch(ClassNotFoundException c)
{
System.out.println(.Product class not found.);
c.printStackTrace();
return;
}
It doesn't look like there is any need for Product to provide readObject and writeObject methods. You should just be able to serialise and deserialise the List as is.
I'd suggest wrapping the list in a class that makes sense in the context. (I don't know what the context is, or what the order is (would a Set be better).) Also mutable statics are generally a bad idea, in particular if you are going to try to serialise and deserialise the referenced object.
The ArrayList class already implements Serializable, and you made your class (Product) serializable; everything seems write to me. "so that the objects in the arraylist will be saved between runtimes." You make it sound like you think it should automatically save them between each time you run it; this might be your mistake. You must write it to a file, and read it the next execution (Use ObjectOutput(/Input)Streams)
Related
How can I deserialize a class which was modified after serialization?
More specifically, I know this can be done when a class had serialVersionUID in its initial version. Is there any way to do it for classes without serialVersionUID?
I have an object
package com.test.serialize;
import java.io.Serializable;
public class MyObject implements Serializable{
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
and I serialize classes like this
package com.test.serialize;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class SerializeTest {
public static void main(String[] args) {
try {
MyObject myObject = new MyObject();
myObject.setName("Ajit");
ObjectOutputStream objectOStr = null;
ByteArrayOutputStream byteOStr = null;
try {
byteOStr = new ByteArrayOutputStream();
objectOStr = new ObjectOutputStream(byteOStr);
objectOStr.writeObject(myObject);
} catch (IOException e) {
System.out.println(e);
} finally {
try {
if (objectOStr != null)
objectOStr.close();
} catch (IOException e2) {
}
}
FileOutputStream fo = new FileOutputStream(new File("serialize"));
fo.write(byteOStr.toByteArray());
fo.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
and deserialize like this
package com.test.serialize;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.RandomAccessFile;
public class DeserializeTest {
public static void main(String[] args) {
try {
// File f = new File("serialize");
// FileInputStream fs = new FileInputStream(f);
RandomAccessFile raF = new RandomAccessFile("serialize", "r");
byte[] b = new byte[(int)raF.length()];
raF.read(b);
ObjectInputStream oIstream = null;
ByteArrayInputStream bIstream = null;
bIstream = new ByteArrayInputStream(b);
oIstream = new ObjectInputStream(bIstream);
Object finalResult = oIstream.readObject();
System.out.println(finalResult.toString());
} catch (IOException | ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
After some time, I added
#Override
public String toString() {
return "MyObject [name=" + name + ", names=" + names + "]";
}
to MyObject. After adding that I got exceptions like
java.io.InvalidClassException: com.test.serialize.MyObject; local class in
compatible: stream classdesc serialVersionUID = 5512234731442983181, local class
serialVersionUID = -6186454222601982895
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:617)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1622)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1517)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
at com.test.serialize.DeserializeTest.main(DeserializeTest.java:25)
Please help me with this.
Thanks #Gábor Bakos.
This can be solved by creating serialVersionUID for older class (Which signatures should be same as the one during serialization )and adding that serialVersionUID in current class.
serialver -classpath /***PATH***/bin com.test.serialize.MyObject
That returns
com.test.serialize.MyObject: static final long serialVersionUID = 5512234731442983181L;
After that I have added it to my MyObject as below
package com.test.serialize;
import java.io.Serializable;
public class MyObject implements Serializable{
/**
* Added serial version Id of old class, created before adding new fields
*/
private static final long serialVersionUID = 5512234731442983181L;
public MyObject() {
System.out.println("Constructor");
}
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
String names ="Altered after change!";
public String getNames() {
return names;
}
public void setNames(String names) {
System.out.println("Setting names");
this.names = names;
}
#Override
public String toString() {
return "MyObject [name=" + name + ", names=" + names + "]";
}
}
It works fine.
More info refer: serialver
First advice: use serialization, because everything is almost done.
Second advice: use a serialVersionUID and keep it fix with one version: it is here to warn you and prevent confusion between different serialized versions.
So : if you change fields or meaning of fields, change the serialVersionUID.
Then you have your backward compatibility problem.
See this for many ideas: Managing several versions of serialized Java objects
IMHO:
whatever solution you take, keep in mind that your program will be managing objects with partial datas: then you have to manage all cases with or without datas.
if you dont change often your version: use several different classes. Perhaps subclasses, or implementations of an interface: then you can get your program, and you manage several versions of object: MyClass_V1, MyClass_V2, etc. When you deserialize, you can test/retry and get the good Object. After that, you perhaps have to convert datas between your classes
if you change your version, by adding new fields (not changing old fields), it is a little more easy (subclasses, converting is direct to parents)
or you could consider use a XML structure to serialize and deserialize: you can have backward and forward compatibility because it is extensible: fields are there, or are null. You have to manage mapping yourself or use some libraries.
Hope it helps !
I would remember following points,
Every Serializable class contains a serialVersionUID ( it doesn't matter if you have specified the one explicitly or not ).
There are compatible changes and there are incompatible changes
e.g. adding a new field is a compatible change, removing a field is not a compatible change. Adding / removing / editing a method are generally compatible changes but in your case surely that is not the way it is ( serialVersionUID got changed after you added toString() method)
3.Prior to modify the class, you can use serialver utility to find serialVersionUID of old class and use that in new class
Don't think there are any other magic tricks :)
What happens during serialization in java, if two object refrences are pointing to the same serializable Object? Does the Serializable Objects get saved twice ?
for example :
class King implements java.io.Serializable {
private String name="Akbar";
}
class Kingdom implements java.io.Serializable {
King goodKing=new King();
King badKing=goodKing;
}
public class TestSerialization {
public static void serializeObject(String outputFileName,
Object serializableObject) throws IOException {
FileOutputStream fileStream=new FileOutputStream(outputFileName);
ObjectOutputStream outStream=new ObjectOutputStream(fileStream);
outStream.writeObject(serializableObject);
outStream.close();
}
public static void main(String[] args) {
Kingdom kingdom=new Kingdom();
try {
TestSerialization.serializeObject("Kingdom1.out", kingdom);
}catch(IOException ex) {
ex.getMessage();
}
}
}
Now, whether only one object state is saved for both goodKing and badKing refrences or the King object get saved twice ?
The documentation for ObjectOutputStream says what happens:
The default serialization mechanism for an object writes the class of the object, the class signature, and the values of all non-transient and non-static fields. References to other objects (except in transient or static fields) cause those objects to be written also. Multiple references to a single object are encoded using a reference sharing mechanism so that graphs of objects can be restored to the same shape as when the original was written.
(My emphasis)
E.g., if you have multiple references to a single object, when the graph is reconstituted, you end up with multiple references to a single reconstituted version of that object, not references to multiple equivalent instances of it.
Of course, if the container being serialized implements a different mechanism, the behavior is dictated by that mechanism, not the default one.
So for instance, if we have Thing and Test:
Thing.java:
import java.io.*;
import java.util.*;
public class Thing implements Serializable {
private Map<String,String> map1;
private Map<String,String> map2;
public Thing() {
this.map1 = new HashMap();
this.map2 = this.map1; // Referring to same object
}
public void put(String key, String value) {
this.map1.put(key, value);
}
public boolean mapsAreSameObject() {
return this.map1 == this.map2;
}
}
Test.java:
import java.io.*;
public class Test implements Serializable {
public static final void main(String[] args) {
try
{
// Create a Thing
Thing t = new Thing();
t.put("foo", "bar");
// Write it out
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("foo"));
os.writeObject(t);
os.close();
os = null;
// Read it in
Thing t2;
ObjectInputStream is = new ObjectInputStream(new FileInputStream("foo"));
t2 = (Thing)is.readObject();
is.close();
is = null;
// Same underlying map for both properties?
System.out.println("t2.mapsAreSameObject? " + t2.mapsAreSameObject());
}
catch (Exception e)
{
System.out.println("Exception: " + e.getMessage());
}
}
}
And run java Test, we get:
t2.mapsAreSameObject? true
...because both of Thing's members, map1 and map2 end up pointing to a single HashMap instance.
I have an array of objects and I want to write them in a text file. So that I can later read the objects back in an array. How should I do it?
Using Serialization.
Deserialization is not working:
public static void readdata(){
ObjectInputStream input = null;
try {
input = new ObjectInputStream(new FileInputStream("myfile.txt")); // getting end of file exception here
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
try {
array = (players[]) input.readObject(); // null pointer exception here
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
readdata();
writedata();
}
The process of converting objects into strings and vice versa is called Serialization and Deserialization. In order to serialize an object it should implement Serializable interface. Most built-in data types and data structures are serializable by default, only certain classes are not serializable (for example Socket is not serializable).
So first of all you should make your class Serializable:
class Student implements java.io.Serializable {
String name;
String studentId;
float gpa;
transient String thisFieldWontBeSerialized;
}
The you can use ObjectOutputStream to serialize it and write to a file:
public class Writer {
static void writeToFile(String fileName, Student[] students) throws IOException {
File f = new File(fileName);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f));
oos.writeObject(students);
oos.flush();
oos.close();
}
}
ObjectInputStream can be used in a similar way to read the array back from file.
As far as I know, Java doesn't give you an easy way to do this for arbitrary objects. Thus, consider restricting yourself to an array of Serializable.
If the objects you have to handle are of your own classes and you thus want these classes to implement the java.io.Serializable interface, carefully read what 'contract' it comes with, as not all of what you have to guarantee for your class will be enforced programatically at compile-time. (So if your classes implement Serializable without completely following the conditions it poses, you might get runtime errors or just 'wrong' and maybe hard-to-detect runtime behavior.)
(See also these best practices.)
How I can store a value in an array variable say x.
At every instance, whenever we have a value for x or when we don't have a value for x, we can have a time. Like at instance 1 millisec, x has value 245 and at 3 millisec, x has value 300.
How do I do this in Java without using or storing values in a Database?
It's hard to know what you are doing based on the description, but if your intention is to store a piece of intelligence (some integer value, say) with a corresponding monotonically increasing value such as a timestamp in millis, you should use a data structure or object to do so. I often refer to such a fundamenal data piece as an "atom".
If you will never need a more complicated atom than a long - int relationship, you could use some sort of Map.
If you ever intend to make this atom more complicated, you might want to create your own object. The nice thing about this way is that you can build in error handling (e.g., time not increasing monotonically, or apparent gaps). It also makes it a little more straightforward when persisting/caching this data to some store so you can work on datasets larger than memory. This last part is probably the trickiest part of your design.
#Arunroy in base on my understanding of posible question i have a example i wrote. It possibly could help you, it has a class that implements an interface Serializable that enable the class to be serializable in other words to be stored in a file and then be read. This process is called serialization. The class creates a file and store the class inside the file. Then with the deserialization process you can read it.
The code:
package storage;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.sql.Timestamp;
public class MyValues{
public static void main(String[] args) {
java.util.Date date = new java.util.Date();
MyData d = new MyData(new Timestamp(date.getTime()));
System.out.println(""+d.tiempo);
serialize(d);
deSerialize();
}
public static boolean serialize(MyData a) {
try {
FileOutputStream fileOut
= new FileOutputStream("c:\\myfolder1\\mydata.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(a);
out.close();
fileOut.close();
System.out.printf("Serialized data is saved in c:\\myfolder1\\mydata.ser \n");
} catch (IOException i) {
i.printStackTrace();
}
return false;
}
public static void deSerialize() {
MyData a = null;
try {
FileInputStream fileIn = new FileInputStream("c:\\myfolder1\\employee.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
a = (MyData) in.readObject();
in.close();
fileIn.close();
} catch (IOException i) {
i.printStackTrace();
return;
} catch (ClassNotFoundException c) {
System.out.println("Employee class not found");
c.printStackTrace();
return;
}
System.out.println("Deserialized MyData...");
System.out.println("TimeStamp: " + a.tiempo);
return;
}
}
class MyData implements Serializable{
public Timestamp tiempo;
public MyData(Timestamp tiempo) {
this.tiempo = tiempo;
}
}
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.