I can't serialize and deserialize an object in Java - java

I have a problem while serializing an object in Java(8). I saw many examples, but none of them work for me. The thing is that while serializing it doesn't serialize the object with its complete data. When I try to deserialize, it reads all the variables as null. I do this with Employee class. The code for Serialize.java :
public class Serialize {
private static ArrayList<Employee> emp = new ArrayList<Employee>();
public static void main(String[] args){
try{
emp.add(new Employee("Areg Hovhannisyan",5));
emp.add(new Employee("Tigran Hakobyan",15));
emp.add(new Employee("Shivanshu Ojha",11));
FileOutputStream fos = new FileOutputStream("emps.emp");
ObjectOutputStream out = new ObjectOutputStream(fos);
out.writeObject(emp);
out.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Employee.java:
import java.io.Serializable;
public class Employee implements Serializable {
private static int age;
private static String name;
public static int getAge() {
return age;
}
public static void setAge(int age) {
Employee.age = age;
}
public static String getName() {
return name;
}
public static void setName(String name) {
Employee.name = name;
}
public Employee(String name,int i) {
this.name = name;
this.age = i;
}
#Override
public String toString() {
return "Name : " + getName() + ", Age : " + getAge();
}
}
Please give an example to do this,how to deserialize and please give it with a explanation because I also want to understand how it works.

This is because your fields in class are static. Statics are implicitly transient and we can not serialize transient fields.

The only problem in your code is that age and name fields should not be static for what you intend to do...
Your code should work just by removing the two static modifiers.
Then you maybe should read about static modifier to understand why your code couldn't work.

Default serializable fields of a class are defined to be the non-transient and non-static fields.
Oracles Link
Here is stack OverFlow Link for it

As mentioned in the above comments, Statics are implicitly transient. Also as per your code if the variables are static, you'll have one vaule(which is finally added) in your Arraylist. This is the behaviour of static variable.
Please give an example to do this,how to deserialize
Code with Deserialization:
public static void main(String[] args) throws IOException,
ClassNotFoundException {
FileOutputStream fos = null;
ObjectOutputStream out = null;
FileInputStream fis = null;
ObjectInputStream in = null;
try {
emp.add(new Employee("Areg Hovhannisyan", 5));
emp.add(new Employee("Tigran Hakobyan", 15));
emp.add(new Employee("Shivanshu Ojha", 11));
fos = new FileOutputStream("emps.emp");
out = new ObjectOutputStream(fos);
out.writeObject(emp);
fis = new FileInputStream("emps.emp");
in = new ObjectInputStream(fis);
ArrayList<Employee> empRead = (ArrayList) in.readObject();
System.out.println(empRead.get(0));
} catch (IOException e) {
e.printStackTrace();
} finally {
out.close();
fos.close();
}
}

Related

Saving and loading a list in a file

I am currently preparing for an exam and am working on the following task:
How can I pass an ArrayList to a "save" method that stores the list's data and another "load" method that passes the data back?
class Person {
private String firstname;
private String lastname;
private String sortname;
public Person(String firstname, String lastname) {
this.firstname = firstname;
this.lastname = lastname;
updateSortname();
//getter and setter..
According to the task I should use these methods:
public static List<Person> load(String filename) throws IOException {
return ??;
}
public static Person load(DataInputStream in) throws IOException {
return ??;
}
public static void save(String filename, List<Person> list) throws IOException {
}
public static void save(DataOutputStream out, Person person) throws IOException {
}
public static List<Person> unserialize(String filename) throws IOException, ClassNotFoundException {
return ??;
}
public static void serialize(String filename, List<Person> persons) throws IOException {
}
This is the main method that should produce the following output:
[Willy Wonka (WonkaWilly), Charlie Bucket (BucketCharlie), Grandpa Joe
(JoeGrandpa)]
[Willy Wonka (WonkaWilly), Charlie Bucket (BucketCharlie), Grandpa Joe
(JoeGrandpa)]
[Willy Wonka (WonkaWilly), Charlie Bucket (BucketCharlie), Grandpa Joe
(JoeGrandpa)]
public class PersonTest {
public static void main(String[] args) throws IOException, ClassNotFoundException {
List<Person> persons = new ArrayList<>();
persons.add(new Person("Willy", "Wonka"));
persons.add(new Person("Charlie", "Bucket"));
persons.add(new Person("Grandpa", "Joe"));
System.out.println(persons);
Person.save("persons.sav", persons);
persons = Person.load("persons.sav");
System.out.println(persons);
Person.serialize("persons.ser", persons);
persons = Person.unserialize("persons.ser");
System.out.println(persons);
}
}
It should look something like this. But I don't know how I do it for ArrayLists.
public static void save(String filename , Graph graph ) throws IOException{
try (ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream (new FileOutputStream (filename)))) {
out.writeObject (graph);
}
}
public static Graph load (String filename) throws IOException, ClassNotFoundException {
Graph graph = null;
try (ObjectInputStream in = new ObjectInputStream (new BufferedInputStream ( new FileInputStream (filename)))) {
graph = (Graph) in.readObject();
}
return graph;
}
As you need output of the Person Object to be as, we need to override toString() of Person class.
[Willy Wonka (WonkaWilly), Charlie Bucket (BucketCharlie), Grandpa Joe (JoeGrandpa)]
class Person {
//Respective Constructor, Getter & Setter methods
/* Returns the string representation of Person Class.
* The format of string is firstName lastName (lastNameFirstName)*/
#Override
public String toString() {
return String.format(firstName + " " + lastName + "("+ lastName + firstName + ")");
}
}
There are many approaches to writing objects to file. Here is with PrintWriter
Save Objects to File
public static void save(String filename, List<Person> list) throws IOException {
PrintWriter pw = new PrintWriter(new FileOutputStream(fileName));
for (Person person : list) {
pw.println(person.toString());
}
pw.close();
}
Or Use serialization
// You could use serialization mechanism.
To use it, you need to do the following:
Declare the Person class as implementing Serializable:
public class Person implements Serializable {
...
#Override
public String toString() {
return String.format(firstName + " " + lastName + "("+ lastName + firstName + ")");
}
}
Write your list to file:
public static void save(String filename, List<Person> list) throws IOException {
FileOutputStream fos = new FileOutputStream(filename);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(list);
oos.close();
}
Read List from File:
public static List<Person> load(String filename) throws IOException {
FileInputStream fis = new FileInputStream(filename);
ObjectInputStream ois = new ObjectInputStream(fis);
List<Person> list = (List<Person>) ois.readObject();
ois.close();
return list;
}
You can try something like this:
public static void save(String filename , ArrayList<Person> persons) throws IOException{
try (ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream (new FileOutputStream (filename)))) {
for(int i = 0; i < persons.size; i++){
out.writeObject(persons.get(i));
}
}
}

Why overriding of clone() is required in either shallow copy or deep copy.Can't we write any method (method name) for the same purpose

I really don't understand the use of overriding the clone().In case of both shallow and deep cloning we can write any method name and it can serve the purpose.Also we are not using the parent(Object) reference to call the clone method .Then whats the use of overriding please explain.
Shallow Copy
class Person implements Cloneable {
private String name;
protected Object copy() {//method name is copy
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
public void setName(String name) {
this.name = name;
}
}
public class TestClone {
public static void main(String[] args) {
Person ob1 = new Person();
ob1.setName("Bibhu");
Person ob2 = (Person) ob1.copy();
System.out.println(ob1.getClass() == ob2.getClass());//true
}
}
Deep Copy
import java.util.ArrayList;
import java.util.List;
class Company {
private String name;
private List<String> empList = new ArrayList<>();
public Company(String name, List<String> empList) {
this.name = name;
this.empList = empList;
}
public String getName() {
return name;
}
public List<String> getEmpList() {
return empList;
}
public Object copy() {
List<String> tempList = new ArrayList<>();
for (String s : this.empList) {
tempList.add(s);
}
String cName = this.name;
return new Company(cName, tempList);
}
}
public class TestDeepClone {
public static void main(String[] args) {
List<String> empList = new ArrayList<>();
empList.add("Bibhu");
empList.add("Raj");
empList.add("John");
Company c1 = new Company("ABC Company", empList);
Company c2 = (Company) c1.copy();
System.out.println(c1.getClass() == c2.getClass());//true
System.out.println(c1.getEmpList() == c2.getEmpList());//false
}
}
It's just for convention. Even the JavaDoc sais that:
By convention, classes that implement this interface should override
Object.clone (which is protected) with a public method. See
Object.clone() for details on overriding this method.

readExternal() not working as expected?

I am using Externalization in this example. First I serialized the object into the file named "tmp" using writeExternal() method .But when I am deserializing it using readExternal() i am getting the output as follows...
default
The original car is name=Maruti
year2009
age10
The new Car is name=null
year0
age10
Here why the name and the year of the car is not serialized? And if is serialized, why i am getting null and 0 as their values...Please specify..
import java.io.*;
class Car implements Externalizable
{
String name;
int year;
static int age;
public Car()
{
super();
System.out.println("default");
}
Car(String n,int y)
{
name=n;
year=y;
age=10;
}
public void writeExternal(ObjectOutput out) throws IOException
{
out.writeObject(name);
out.writeInt(year);
out.writeInt(age);
}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
{
while(in.available()>0){
name=(String)in.readObject();
year=in.readInt();
age=in.readInt();
}
}
public String toString()
{
return("name="+name+"\n"+"year"+year+"\n" +"age" +age);
}
}
public class ExternExample
{
public static void main(String args[])
{
Car car=new Car("Maruti",2009);
Car newCar=null;
try{
FileOutputStream fout=new FileOutputStream("tmp");
ObjectOutputStream so=new ObjectOutputStream(fout);
so.writeObject(car);
so.flush();
}
catch(Exception e){System.out.println(e);}
try
{
FileInputStream fis=new FileInputStream("tmp");
ObjectInputStream oin=new ObjectInputStream(fis);
newCar = (Car) oin.readObject();
}
catch(Exception e){System.out.println(e);}
System.out.println("The original car is "+car);
System.out.println("The new Car is "+newCar);
}
}**
Get rid of the loop and the available() test. You've only written one object, so you should only read one object, so there is no reason to loop, let alone call available(). There are few correct uses of that method, and this isn't one of them.
If you extended Serializable instead of Externalizable and simply removed the read/writeExternal() methods it would work just as well.
Your main method isn't closing the ObjectOutputStream or ObjectInputStream.

Serialization - not working

I create class with methods like a How to serialize an object into a string
and it every say error "java.lang.ClassCastException: java.lang.String cannot be cast to Myclass"
My codes:
1)
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import javax.xml.bind.DatatypeConverter;
public class Serialization {
public static Object fromString(String s) throws IOException,
ClassNotFoundException {
byte[] data = DatatypeConverter.parseBase64Binary(s);
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(
data));
Object o = ois.readObject();
ois.close();
return o;
}
public static String toString(Serializable o) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.close();
return DatatypeConverter.printBase64Binary(baos.toByteArray());
}
}
2) - calling
MyClass hl = (MyClass) Serialization.fromString(items
.getString("data"));
hl.load(); // this is my method from class
3) MyClass - Hologram
public class Hologram implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private Location loc;
private String name;
private String displayname;
public ArmorStand stand;
public Hologram(String name, String displayname, Location loc) {
this.loc = loc;
this.name = name;
this.displayname = displayname;
ArmorStand as = (ArmorStand) loc.getWorld().spawnEntity(loc,
EntityType.ARMOR_STAND);
as.setGravity(false);
as.setCanPickupItems(false);
as.setCustomName(displayname);
as.setCustomNameVisible(true);
as.setVisible(false);
this.stand = as;
HologramManager.holograms.put(name, this);
}
public void move(Location loc) {
this.loc = loc;
stand.teleport(loc);
}
public Location getLocation() {
return this.loc;
}
public void remove() {
stand.remove();
HologramManager.holograms.remove(name);
}
public void removeHologram() {
HologramManager.remove(name);
}
public void changeName(String name) {
HologramManager.holograms.remove(this.name);
this.name = name;
HologramManager.holograms.put(name, this);
}
public void changeDisplayName(String displayName) {
this.displayname = displayName;
stand.setCustomName(displayname);
stand.setCustomNameVisible(true);
}
public void load() {
//todo
}
}
Based on the linked answer, the problem most likely lies in the code you aren't showing us. When you serialize your MyClass object, you are probably doing something like this:
MyClass hl;
String base64String = Serialization.toString(hl.toString());
However you should be calling it like this:
MyClass hl;
String base64String = Serialization.toString(hl);
If you pass a String to the serialization function, you'll get a String back when you call Serialization.fromString(). You want to get an object back that you can cast to a MyClass instance, so pass one of those into Serialization.toString().
The fromString() method in Serilization returns an Object, which you wouldnt be able to cast to the class MyClass. The below line is causing the classCastException
MyClass hl = (MyClass) Serialization.fromString(items
.getString("data"));

Java Serialization for Extended Class

In java serialization class Mp3player extends ElectronicDevice implements Serializable in this code super class electronicdevice is not implemented serializable. here super class is also getting serialized. my understanding is super class is also gets serialized due to extends.let me know my understanding is correct or not.
import java.io.*;
class ElectronicDevice {
ElectronicDevice()
{
System.out.print("ed ");
}
}
class Mp3player extends ElectronicDevice implements Serializable {
Mp3player()
{
System.out.print("mp ");
}
}
class MiniPlayer extends Mp3player {
MiniPlayer()
{
System.out.print("mini ");
}
public static void main(String[] args) {
MiniPlayer m = new MiniPlayer();
try {
FileOutputStream fos = new FileOutputStream("dev.txt");
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(m); os.close();
FileInputStream fis = new FileInputStream("dev.txt");
ObjectInputStream is = new ObjectInputStream(fis);
MiniPlayer m2 = (MiniPlayer) is.readObject();
is.close();
System.out.println();
} catch (Exception x) {
System.out.print("x ");
}
}
}
No.During the process of serialization only the fields of Serializable objects are written out and restored.
According to javadocs
During deserialization, the fields of non-serializable classes will be initialized using the public or protected no-arg constructor of the class.
Where as the fields of serializable subclasses will be restored from the stream.
Please look into this example
Here ElectronicDevice is not Serializable,where as Mp3player is Serializable.Observe the fields of respected classes behaviour in serialization process.
import java.io.*;
class ElectronicDevice {
public int i = 0;
protected ElectronicDevice()
{
System.out.println("ed ");
}
}
class Mp3player extends ElectronicDevice implements Serializable {
int j =0;
Mp3player()
{
System.out.println("mp ");
}
}
class MiniPlayer extends Mp3player {
MiniPlayer()
{
System.out.println("mini ");
}
public static void main(String[] args) {
MiniPlayer m = new MiniPlayer();
m.i = 30;
m.j = 40;
try {
System.out.println("i value before serialization: "+m.i);//prints 30
System.out.println("i value before serialization: "+m.j);//prints 40
FileOutputStream fos = new FileOutputStream("dev.txt");
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(m); os.close();
FileInputStream fis = new FileInputStream("dev.txt");
ObjectInputStream is = new ObjectInputStream(fis);
MiniPlayer m2 = (MiniPlayer) is.readObject();
is.close();
System.out.println("i value after serialization: "+m2.i);//prints o
System.out.println("j value after serialization: "+m2.j);//prints 40
System.out.println();
} catch (Exception x) {
x.printStackTrace();
System.out.print("x ");
}
}
}
Since super class doesn't implement Serializable contents of the super class wont get serialized. Only the contents of the subclass would get serialized. When you deserialize the default constructor of the superclass would get executed and the fields of the superclass initialized as if you invoked the default constructor.
Following example illustrates this.
public class SerializationTest {
public static class Base {
private String name;
public Base() {
this.name = "johnDow";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public static class Sub extends Base implements Serializable {
private static final long serialVersionUID = 1L;
private String age;
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
public static void main(String[] args) throws Exception {
ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteArrayOS);
Sub s = new Sub();
s.setName("name");
s.setAge("10");
out.writeObject(s);
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(byteArrayOS.toByteArray()));
Sub d = (Sub) ois.readObject();
System.out.println(d.getName() + "-" + d.getAge());
}
}
What gets printed is
johnDow-10
This is the rule for superclass serialization:
If you are a serializable class, but your superclass is NOT
serializable, then any instance variables you INHERIT from that
superclass will be reset to the values they were given during the
original construction of the object. This is because the
nonserializable class constructor WILL run.
Therefore, if you add some instance variables to ElectronicDevice, be aware that the superclass 's state will be not serialized. (unless the superclass implements Serializable)
my understanding is super class is also gets serialized due to
extends.let me know my understanding is correct or not.
The short answer is NO.
In java, every class is a subclass of Object. Does Object itself implement Serializable?
To allow subtypes of non-serializable classes to be serialized, the subtype may assume responsibility for saving and restoring the state of the supertype's public, protected, and (if accessible) package fields”
Reference -
http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html

Categories

Resources