Page 1 of 1

About Question enthuware.ocpjp.v7.2.1390 :

Posted: Sat Sep 12, 2015 12:23 pm
by Danny Sheridan
Is it okay to declare throws Exception for these methods?
Doesn't this feature need the specific throws clauses ?

Code: Select all

private void writeObject(ObjectOutputStream out) throws IOException;
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;

Re: About Question enthuware.ocpjp.v7.2.1390 :

Posted: Sat Sep 12, 2015 12:49 pm
by Danny Sheridan
I think I see where I was mistaken.
In interface Serializable docs it says:
Classes that require special handling during the serialization and deserialization process
must implement special methods with these exact signatures
exact signatures - that's just method name and parameter types and order
But not the throws declaration
So when the JVM checks by reflection for these methods it identifies them by signature.
So any throws that covering the exceptions thrown would do.
Is this on the right track?

Re: About Question enthuware.ocpjp.v7.2.1390 :

Posted: Sat Sep 12, 2015 7:27 pm
by admin
You are correct. Throws clause becomes important when you override a method.

Re: About Question enthuware.ocpjp.v7.2.1390 :

Posted: Wed Oct 17, 2018 2:50 pm
by zhengye1
I try to create the program to understand this question, however when I try to run the program I got

Code: Select all

Exception in thread "main" java.io.NotActiveException: not in call to writeObject
	at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:436)
	at ocp.wrongq.Portfolio.writeObject(Portfolio.java:29)
	at ocp.wrongq.Portfolio.main(Portfolio.java:46)
Here is my program:

Code: Select all

// In Portfolio.java
package ocp.wrongq;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

class Bond {

	String ticker = "bac";
	double coupon = 8.3;

	@Override
	public String toString() {
		return "Bond [ticker=" + ticker + ", coupon=" + coupon + "]";
	}
}

public class Portfolio extends Bond implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 2252868398846453877L;
	String accountName;
	transient Bond bond = new Bond();

	private void writeObject(ObjectOutputStream os) throws Exception {
		os.defaultWriteObject();
		os.writeObject(bond.ticker);
		os.writeDouble(bond.coupon);
	}

	private void readObject(ObjectInputStream os) throws Exception {
		os.defaultReadObject();
		this.bond = new Bond();
		bond.ticker = (String) os.readObject();
		bond.coupon = os.readDouble();
		System.out.println(this.bond);
	}

	public static void main(String[] args) throws Exception{
		Portfolio p = new Portfolio();
		FileOutputStream fos = new FileOutputStream("t.tmp");
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		p.writeObject(oos);
		FileInputStream fis = new FileInputStream("t.tmp");
		ObjectInputStream ios = new ObjectInputStream(fis);		
		p.readObject(ios);
	}
}
What did I do wrong?

Re: About Question enthuware.ocpjp.v7.2.1390 :

Posted: Wed Oct 17, 2018 10:34 pm
by admin
You need to change p.writeObject(oos); to oos.writeObject(p);
and p.readObject(ios); to ios.readObject(p);

Re: About Question enthuware.ocpjp.v7.2.1390 :

Posted: Wed Oct 17, 2018 10:51 pm
by zhengye1
But if we did this change, how to invoke that two private method?

Re: About Question enthuware.ocpjp.v7.2.1390 :

Posted: Wed Oct 17, 2018 11:11 pm
by admin

Re: About Question enthuware.ocpjp.v7.2.1390 :

Posted: Thu Dec 06, 2018 5:55 am
by bortnikov_sa@mail.ru
Hellow. Is it ok to use: os.writeObject(accountName) and accountName = (String) os.readObject() instead os.defaultWriteObject() and os.defaultReadObject() respectively?

Re: About Question enthuware.ocpjp.v7.2.1390 :

Posted: Thu Dec 06, 2018 9:54 am
by admin
No, both the methods have different purpose. defaultReadObject can only be called from within the implementation of readObject. Please take look at their API description.

Re: About Question enthuware.ocpjp.v7.2.1390 :

Posted: Tue Mar 05, 2019 12:05 pm
by crazymind
hi, I don't quite understand why this code keep Bond as transient and serialize its fields explicitly?
And if we don't override writeObject(), will writeObject() call defaultWriteObject() internally? Thanks!

Re: About Question enthuware.ocpjp.v7.2.1390 :

Posted: Tue Mar 05, 2019 10:11 pm
by admin
Because Bond class does not implement Serializable interface. If you try to serialize a Portfolio object, it will fail because it contains a Bond field, which cannot be serialized by the default serialization mechanism. That is why we have to implement our own customized serialization logic for Portfolio class so that information contained in Bond is saved and can be read back later while deserialization.

Re: About Question enthuware.ocpjp.v7.2.1390 :

Posted: Thu Sep 26, 2019 9:29 am
by radionoise
bortnikov_sa@mail.ru wrote:
Thu Dec 06, 2018 5:55 am
Hellow. Is it ok to use: os.writeObject(accountName) and accountName = (String) os.readObject() instead os.defaultWriteObject() and os.defaultReadObject() respectively?
admin wrote:
Thu Dec 06, 2018 9:54 am
No, both the methods have different purpose. defaultReadObject can only be called from within the implementation of readObject. Please take look at their API description.
I don't see a reason why calling os.writeObject(accountName) instead of os.defaultWriteObject() and this.accountName = (String) os.readObject() instead of os.defaultReadObject() not woking.

Code: Select all

class Bond {
    String ticker = "bac";
    double coupon = 8.3;
}

class Portfolio implements Serializable {
    String accountName;
    transient Bond bond = new Bond();

    private void writeObject(ObjectOutputStream os) throws Exception {
        os.writeObject(accountName);
        os.writeObject(bond.ticker);
        os.writeDouble(bond.coupon);
    }

    private void readObject(ObjectInputStream os) throws Exception {
        this.accountName = (String) os.readObject();
        this.bond = new Bond();
        bond.ticker = (String) os.readObject();
        bond.coupon = os.readDouble();
    }
}