Java Serialization for Extended Class - java

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

Related

Serialization of inner class (Java)

I have class Solution, that contains inner class A, class B, class C.
Class B extends class A, class C extends class B.
I want class C to be Serializable, so I implements Serializable in class C and in class Solution (class C is inner class of class Solution).
Because class C extends class B and class B extends class A, I create a no-arg constructor in class B and class A (I don't want them implements Serializable).
So the following code:
public class Solution implements Serializable {
public class A {
String name = "A";
public A(String name) {
this.name += name;
}
public A() {}
}
public class B extends A {
String name = "B";
public B(String name) {
super(name);
this.name += name;
}
public B() {}
}
public class C extends B implements Serializable {
String name;
public C(String name) {
super(name);
this.name = name;
}
}
}
public class Test {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Solution.C c = new Solution().new C("C");
System.out.println(c.name);
System.out.println("serialization");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\1.txt"));
oos.writeObject(c);
oos.close();
System.out.println("deserialization");
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\1.txt"));
Solution.C c1 = (Solution.C) ois.readObject();
ois.close();
System.out.println(c1.name);
}
}
throws the following exception:
C
serialization
deserialization
Exception in thread "main" java.io.InvalidClassException: Test3.Solution$C; no valid constructor
What happens in your case is that the deserialization code is eventually going to construct an instance of ObjectStreamClass for your class Solution.C. In the constructor of this class, it tries to find a constructor of the class to deserialize that is suitable. In your case, it will call ReflectionFactory#newConstructorForSerialization. Here's what the documentation of this method says:
Returns a constructor that allocates an instance of cl and that then initializes the instance by calling the no-arg constructor of its first non-serializable superclass. This is specified in the Serialization Specification, section 3.1, in step 11 of the deserialization process. If cl is not serializable, returns cl's no-arg constructor. If no accessible constructor is found, or if the class hierarchy is somehow malformed (e.g., a serializable class has no superclass), null is returned.
Your first non-serializable superclass is B, however B has no no-arg constructor because all its constructors have a synthetic parameter of type Solution. Thus, no constructor is found and deserialization fails. When you make B and A serializable, it works because newConstructorForSerialization will go up to Object (see loop below) and use its no-arg constructor.
public final Constructor<?> newConstructorForSerialization(Class<?> cl) {
Class<?> initCl = cl;
while (Serializable.class.isAssignableFrom(initCl)) {
Class<?> prev = initCl;
if ((initCl = initCl.getSuperclass()) == null ||
(!disableSerialConstructorChecks && !superHasAccessibleConstructor(prev))) {
return null;
}
}
Constructor<?> constructorToCall;
try {
constructorToCall = initCl.getDeclaredConstructor();
int mods = constructorToCall.getModifiers();
if ((mods & Modifier.PRIVATE) != 0 ||
((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
!packageEquals(cl, initCl))) {
return null;
}
} catch (NoSuchMethodException ex) {
return null;
}
return generateConstructor(cl, constructorToCall);
}
Can you just avoid doing this altogether? Reading the answers to this question, it seems strongly discouraged to serialized inner instances like you're doing now (full explanation in the link). You're giving yourself a hard time trying to do this, but at least now we know why this was failing.
Default constructor for parent classes are not required. Making class A as serializable it will work. You may also remove the serialization from class C.
public class Solution implements Serializable {
public class A implements Serializable{
String name = "A";
public A(String name) {
this.name += name;
}
public A() {}
}
public class B extends A {
String name = "B";
public B(String name) {
super(name);
this.name += name;
}
public B() {}
}
public class C extends B {
String name;
public C(String name) {
super(name);
this.name = name;
}
}
}

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.

I can't serialize and deserialize an object in 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();
}
}

Serialize java class with custom object attributes

I would like to serialize a Java class on my MySQL database using Ebean ORM.
My class definition is similar to the following:
public class Test implements Serializable
{
#Id
private Long id;
...
...
...
#Lob
private MyClass1 obj1;
#Lob
private MyClass2 obj2;
...
...
//getters and setters
}
where my classes MyClass1 and MyClass2 are basically wrappers for a
float[]
and an
Hashmap<String, Float>
and both implement Serializable interface.
I don't want to have to create a class with:
#Lob
byte[] obj1bytes;
#Transient
MyClass1 obj1Obj;
#Lob
byte[] obj2bytes;
#Transient
MyClass2 obj2Obj;
//getters and setters
What I would like to obtain is serialize and deserialize this class automatically WITHOUT having to use byte[] arrays to hold obj1 and obj2 in my Test class to a MySQL table in two LongBlob fields using
Ebean.save(testClassInstance);
Ebean.find(Test.class, ID);
EDIT1: MyClass1 is defined as following:
public class MyClass1 implements Interface1 {
private float[] vector;
public MyClass1 () {
}
public MyClass1 (float[] vector) {
this.vector = vector;
}
public float[] getVector() {
return vector;
}
public void setVector(float[] vector) {
this.vector = vector;
}
#Override
public byte[] serialize() throws Exception {
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteOut);
out.writeObject(object);
out.close();
return byteOut.toByteArray();
}
#Override
public void deserialize(byte[] bytes) throws Exception {
ByteArrayInputStream byteInt = new ByteArrayInputStream(bytes);
ObjectInputStream out = new ObjectInputStream(byteInt);
vector = (float[])out.readObject();
}
#Override
public float cossim(MyClass1 v) throws Exception {
method logic
}
#Override
public MyClass1 add(MyClass1 v) throws Exception {
method logic
}
}
MyClass2 is defined as MyClass1, only that instead of float[] vector I have a HashMap < String, Float > (). The only differences worth noting are serialize() and deserialize():
#Override
public byte[] serialize() throws Exception {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(outStream);
out.writeInt(map.size());
Iterator<String> iterator = map.keySet().iterator();
while (iterator.hasNext()) {
String key = iterator.next();
out.writeUTF(key);
out.writeFloat(map.get(key));
}
return outStream.toByteArray();
}
#Override
public void deserialize(byte[] bytes) throws Exception {
try {
ByteArrayInputStream inStream = new ByteArrayInputStream(bytes);
DataInputStream in = new DataInputStream(inStream);
this.map = new HashMap<>();
int n = in.readInt();
for (int i = 0; i < n; i++) {
map.put(in.readUTF(), in.readFloat());
}
} catch (Exception ex) {
throw ex;
}
}
Actually it is not necessary to wrap float[] and HashMap<String,float> as they themselves are serializable.
Another thing is that if MyClass1 and MyClass2 are serializable than you can use #Lob. According to this wikibook,
By default in JPA any Serializable attribute that is not a
relationship or a basic type (String, Number, temporal, primitive),
will be serialized to a BLOB field.
In that wikibook, there is also an example using #Lob for the class Image.
#Entity
public class Employee {
...
#Basic(fetch=FetchType.LAZY)
#Lob
private Image picture;
...
}
Hope this might help you.
I did some coding after your reply.
Condition: The fields of ClassB should be serializable and the fields of fields should be serializable and ....
ClassB:
import java.io.Serializable;
public class ClassB implements Serializable{
private static final long serialVersionUID = 1L;
String b;
public String getB() {
return b;
}
public void setB(String b) {
this.b = b;
}
}
ClassA:
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Lob;
#Entity
public class ClassA implements Serializable{
private static final long serialVersionUID = 1L;
#Id
String a;
#Lob
ClassB b;
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
public ClassB getB() {
return b;
}
public void setB(ClassB b) {
this.b = b;
}
}
Here, ClassA contains ClassB object. You can add any logic in ClassB and it works. I have small problem with your overriding of serialize and deserialize. I think you do not need to do that. It will be done by default as it is serialized. And at last, these codes do work as I have tried it.
Hope this will help you.

Serialization of polymorphic objects

I have classes Osoba(Person) and Zawodnik(Constestant)
Contestant extends Person and Person implements Serializable. Does Constestant automatically implements Serializable too? I think so.
The extension (ArrayList ekstensja) of class Person contains objects of different classes extending class Person. Will the method zapiszEkstensje() in the Person class work correctly? I think so.
Example:
public abstract class Osoba implements Serializable {
/....something..../
private static ArrayList<Osoba> ekstensja = new ArrayList<Osoba>();
private void dodajZawodnik(Osoba osoba) {
ekstensja.add(osoba);
}
private void usunZawodnik(Osoba osoba) {
ekstensja.remove(osoba);
}
public static void pokazEkstensje() {
for (Osoba zawodnik : ekstensja)
System.out.println(zawodnik + "\n");
}
public static void zapiszEkstensje() {
try {
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("osoba.ser"));
outputStream.writeObject(ekstensja);
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
#SuppressWarnings("unchecked")
public static void wczytajEkstensje(){
try {
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("osoba.ser"));
ekstensja = (ArrayList<Osoba>) (inputStream.readObject());
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class Zawodnik extends Osoba { }
// DO I NEED TO MAKE THIS CLASS IMPLEMENT SERIALIZABLE TOO?
According to java doc of Serializable interface, all the subtypes of a serializable class are themselves serializable.
So, the answer is yes, if Person implements Serializable all its children will be serializable.

Categories

Resources