readExternal() not working as expected? - java

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.

Related

Manipulate Java object reference using class constructor

This was an exam question which I couldn't complete.
How do you get the following java code to print false by only
editing code within the MyClass constructor?
public class MyClass{
public MyClass(){
}
public static void main(String[] args) {
MyClass m = new MyClass();
System.out.println(m.equals(m));
}
}
You are NOT allowed to override the equals method, or change any of
the code within the main method. The code must run without the program
crashing.
According to my research, you can't set a Java object reference to null when you instantiate a class. So I'm officially stumped.
That was tough!!
public MyClass() {
System.setOut(new PrintStream(new FilterOutputStream(System.out) {
#Override
public void write(byte[] b, int off, int len) throws IOException {
if(new String(b).contains("true")) {
byte[] text = "false".getBytes();
super.write(text, 0, text.length);
}
else {
super.write(b, off, len);
}
}
}, true));
}
Or Paul Boddington's simplified version:
PrintStream p = System.out;
System.setOut(new PrintStream(p) {
#Override
public void println(boolean b) {
p.println(false);
}
});
Or AJ Neufeld's even more simple suggestion:
System.setOut(new PrintStream(System.out) {
#Override
public void println(boolean b) {
super.println(false);
}
});
Something along these lines, I would guess:
public MyClass() {
System.out.println(false);
System.exit(0);
}
EDIT: I found a puzzle very similar to yours in Java Puzzlers, except in that question the only restriction was that you could not override equals, which basically makes the solution to overload it instead and simply return false. Incidentally, my solution above was also given as an alternative answer to that puzzle.
Another solution is
public MyClass() {
new PrintStream(new ByteArrayOutputStream()).println(true);
try {
Field f = String.class.getDeclaredField("value");
f.setAccessible(true);
f.set("true", f.get("false"));
} catch (Exception e) {
}
}
The first line is needed because it is necessary for the string literal "true" to be encountered in the PrintStream class before the backing array is modified. See this question.
This is my solution
public class MyClass {
public MyClass() {
System.out.println("false");
// New class
class NewPrintStream extends PrintStream {
public NewPrintStream(OutputStream out) {
super(out);
}
#Override
public void println(boolean b) {
// Do nothing
}
}
NewPrintStream nps = new NewPrintStream(System.out);
System.setOut(nps);
}
public static void main(String[] args) {
MyClass m = new MyClass();
System.out.println(m.equals(m));
}
}
Basically, this is the variation of #fikes solution.

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();
}
}

Why Java complains "No Valid Constructor" even when default constructor is present?

public class ExternalizableClass implements Externalizable
{
public static ExternalizableClass CACHE = new ExternalizableClass(-1);
int id;
public ExternalizableClass()
{
id = (int)(Math.random() * 1000);
}
public ExternalizableClass(int i)
{
id = i;
}
#Override
public void writeExternal(ObjectOutput out) throws IOException
{
out.writeInt(id);
}
#Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
{
//id = in.readInt();
id = in.readInt();
}
public Object writeReplace() throws ObjectStreamException
{
return new Write(0);
}
private class Write extends ExternalizableClass
{
int value;
public Write()
{
}
public Write(int i)
{
value = i;
}
public Object readResolve() throws ObjectStreamException
{
return ExternalizableClass.CACHE;
}
}
#Override
public String toString()
{
return "id: " + id;
}
public static void main(String[] argv)
{
try
{
ExternalizableClass ex = ExternalizableClass.CACHE;
System.out.println(ex);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("temp.txt"));
oos.writeObject(ex);
oos.close();
}
catch (Exception e)
{
e.printStackTrace();
}
ExternalizableClass ex;
try
{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("temp.txt"));
ex = (ExternalizableClass) ois.readObject();
System.out.println(ex);
ois.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
Both ExternalizableClass and ExternalizableClass.Write class have default (non-arg) constructors. But when deserializing it, Java complains:
java.io.InvalidClassException: SeralizableTest.ExternalizableClass$Write; no valid constructor
at java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.java:150)
at java.io.ObjectStreamClass.checkDeserialize(ObjectStreamClass.java:768)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1772)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
at SeralizableTest.ExternalizableClass.main(ExternalizableClass.java:124)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Can anyone explain what the problems are?
I suspect the problem is that it's an inner class... so it doesn't actually have a parameterless constructor. Instead, it has two constructors, one of which takes a reference to an instance of the enclosing class, and one of which takes a reference to an instance of the enclosing class and an int.
If you make it just a nested class by adding the static modifier to the class declaration (for Write) then I suspect it'll be fine, because then it won't have the implicit extra parameter on each constructor.

Java Serializing Objects Like an Area

I have read a little bit about 3rd party serialization methods such as JSON, but was wondering if there is any other way to serialize objects such as an area that do not implement serializable. In other word would JSON be the best way to serialize such an object?
EDIT : Throwing A NotSerializable Exception
public class Test {
public static void main(String[] args) throws Exception {
Pojo pojo = new Pojo(new Area()); // The original object, NOT SERIALIZABLE !
byte[] pojoBytes = Serializer.serialize(pojo); // Serialize
pojo = (Pojo) Serializer.deserialize(pojoBytes); // Deserialize
System.out.println(pojo); // Good as new !
}
}
public class Pojo implements Serializable {
private final Area msg;
public Pojo(Area msg) {
this.msg = msg;
}
public Area getMsg() {
return msg;
}
public String toString() {
return "Pojo says : " + msg;
}
}
public class Serializer {
public static byte[] serialize(Object o) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
FileOutputStream fileOut = new FileOutputStream("Test.ser");
ObjectOutputStream oos = new SurrogateObjectOutputStream(fileOut); // Magically handle Pojos !
oos.writeObject(o);
oos.flush();
oos.close();
return baos.toByteArray();
}
public static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
FileInputStream fileIn = new FileInputStream("Test.ser");
ObjectInputStream ois = new ObjectInputStream(fileIn);
Object o = ois.readObject();
bais.close();
return o;
}
}
public class SurrogateObjectOutputStream extends ObjectOutputStream {
public SurrogateObjectOutputStream(OutputStream out) throws IOException {
super(out);
enableReplaceObject(true);
}
protected SurrogateObjectOutputStream() throws IOException, SecurityException {
super();
enableReplaceObject(true);
}
#Override
protected Object replaceObject(Object obj) throws IOException {
if (obj instanceof Pojo) {
return new PojoSurrogate((Pojo) obj);
} else return super.replaceObject(obj);
}
}
public class PojoSurrogate implements Serializable {
private Area foo;
public PojoSurrogate(Pojo pojo) {
this.foo = pojo.getMsg();
}
private Object readResolve() throws ObjectStreamException {
return new Pojo(foo);
}
}
It depends, if you want to use that Object in another program or another language for that matter, then yes JSON is the way to go (or XML).
But if you want to reuse that Object in another JAVA program then I guess it would be more convenient to look for a way to make possible non-serializable Objects serializable.
I haven't tested it yet, but I found a promising solution in this blog (which is in French, sorry). I'll try my best to summarize it:
what you have
say you have a class names Pojo and you want to serialize it although you don't know if it is serializable or not.
public final class Pojo {
private final String msg;
public Pojo(String msg) {
this.msg = msg;
}
public String getMsg() {
return msg;
}
public String toString() {
return "Pojo says : " + msg;
}
}
what you need
what you need is a new class that acts as a surrogate, which will take the member variables of the real Pojo and simply replace it.
public class PojoSurrogate implements Serializable {
private String foo;
public PojoSurrogate(Pojo pojo) {
this.foo = pojo.getMsg();
}
private Object readResolve() throws ObjectStreamException {
return new Pojo(foo);
}
}
the last method ( readResolve() ) is the one that will in the end give you back your new Pojo later.
The other thing you need is your own surrogate version of the ObjectOutputStream:
public class SurrogateObjectOutputStream extends ObjectOutputStream {
public SurrogateObjectOutputStream(OutputStream out) throws IOException {
super(out);
enableReplaceObject(true);
}
protected SurrogateObjectOutputStream() throws IOException, SecurityException {
super();
enableReplaceObject(true);
}
#Override
protected Object replaceObject(Object obj) throws IOException {
if (obj instanceof Pojo) {
return new PojoSurrogate((Pojo) obj);
} else return super.replaceObject(obj);
}
}
And again here the last method replaceObject() will do the magic and transform the Pojo into the serializable version PojoSurrogate to store all the information as bytes.
Serialize like this
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new SurrogateObjectOutputStream(baos);
oos.writeObject(o);
oos.flush();
oos.close();
byte[] serializedPojo = baos.toByteArray();
Deserialize normally
ObjectInputStream bais = new ObjectInputStream(new ByteArrayInputStream( serializedPojo ));
Pojo myNewPojo = (Pojo) bais.readObject();
bais.close();
Sorry, long answer.. and I hope I haven't missed anything supercool from that blog where it is easier to create a more scalable solution.. hope this helps anyway!
[EDIT:]
I tried your code with an Area object and here is how I got some thing to work (although I am not sure if this is actually working with all Areas, so you might have to test if your areas still have the same characteristics after deserialization)
AreaSurrogate
public class AreaSurrogate implements Serializable {
private final Rectangle bounds;
public AreaSurrogate(Area area) {
this.bounds = area.getBounds();
}
private Object readResolve() throws ObjectStreamException {
return new Area(bounds);
}
}
SurrogateOutputStream
public class SurrogateOutputStream extends ObjectOutputStream {
public SurrogateOutputStream(OutputStream out) throws IOException {
super(out);
enableReplaceObject(true);
}
protected SurrogateOutputStream() throws IOException, SecurityException {
super();
enableReplaceObject(true);
}
#Override
protected Object replaceObject(Object obj) throws IOException {
if (obj instanceof Area) {
return new AreaSurrogate((Area) obj);
} else {
return super.replaceObject(obj);
}
}
}
Serializer
public class Serializer {
public static byte[] serialize(Object o) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new SurrogateOutputStream(baos); // Magically handle Pojos !
oos.writeObject(o);
oos.flush();
oos.close();
return baos.toByteArray();
}
public static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais);
Object o = ois.readObject();
bais.close();
return o;
}
}
Main (to test)
public static void main(String[] args) throws Exception {
Area area = new Area(new Rectangle(0, 0, 100, 100)); // The original object, NOT SERIALIZABLE !
System.out.println(area.contains(new Rectangle(1, 1, 10, 10))); // Good as new !
System.out.print("serializing...");
byte[] pojoBytes = Serializer.serialize(area); // Serialize
System.out.println("done");
System.out.print("deserializing...");
area = (Area) Serializer.deserialize(pojoBytes); // Deserialize
System.out.println("done");
System.out.println(area.contains(new Rectangle(1, 1, 10, 10))); // Good as new !
}
In the main() I create an Area from a Rectangle which starts at Coordinate (0,0) and is 100 wide and 100 high. Then I test if the Rectangle from (1,1) with 10 width and 10 height is inside the area (which it is, forcibly). After serializing and deserializing I test if the same Rectangle is still inside the new Area.
This might be insufficient, since the new Area Object is created from a Rectangle (see AreaSurrogate). so this might not work with other Area shapes..
expected output
true
serializing...done
deserializing...done
true

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