My mistake, thank you.

Peter.

On 5/01/2015 9:57 PM, David Holmes wrote:
Hi Peter,

Did you send this to the list? I haven't seen it turn up yet.

David

On 5/01/2015 6:51 PM, Peter Firmstone wrote:
Thanks Dave,

That's another way of checking invariants, you could expose A's check
method but you'd also need a couple of additional static methods to
obtain integers upper and lower from ReadSerial, so that B can ensure
its invariant.

ReadSerial is caller sensitive so B can't obtain A's stream values via
ReadSerial and must do so via A's API.  This prevents the publication of
A's implementation, you don't wan't B depending on A's serial form.
Instead A can reorder and rename it's fields and change their values,
have multiple serial forms and be able to remain compatible with all
forms relatively easily.

There are some benefits to using a temporary object instance of A; it
reduces the amount of code required, eg it would be a beneficial for RMI
to minimise code downloads, the JVM is free to inline access to these
fields and the temporary instance of A never leaves the cpu cache, so
it's not likely to become a performance issue.  Well it might on real
time java :)

If circular relationships are mutable, or effectively mutable after
publication, then we could eventually deprecate the requirement to
support special treatment of final fields for Serializable.

Cheers,

Peter.

On 5/01/2015 10:38 AM, David Holmes wrote:

      - I don't see how this invariant-checking mechanism can enforce
invariants between superclass fields and subclass fields.   For
example:

class A {
            int lower, upper;   // invariant: lower <= upper
}

class B extends A {
            int cur;   // invariant: lower <= cur <= upper
}


The serialization framework should only construct an objects fields
and make these available from ReadSerial, each class then calls a
static method before calling a superclass constructor that's
responsible for an objects creation, to prevent construction of the
object, if necessary.

Eg, some complexity, but bullet proof:

public class A (

     public final int lower, upper;

      private static boolean check(ReadSerial rs){
         if (rs.getInt("lower") > rs.getInt("upper"))
              throw new IllegalArgumentException(
                 "lower bound must be less than or equal to upper");
        return true;
     }

     public A(ReadSerial rs){
         this(check(rs), rs);
     }

     private A(boolean checked, ReadSerial rs){
         super();
         lower = rs.getInt("lower");
         upper = rs.getInt("upper");
     }

// other constructors omitted must also check invarients
}

class B extends A {

     public final int cur;

     private static ReadSerial check(ReadSerial rs) {
         A a = new A(rs);


It doesn't seem practical in general to have to create an instance of
your supertype to validate the passed in serialized form. Why not
expose the check method?

David
-----

         int cur = rs.getInt("cur");
         if ( a.lower > cur || cur > a.upper )
              throw new IllegalArgumentException(
                  "cur outside lower and upper bounds");
         return rs;
     }

     public B(ReadSerial rs) {
         super(check(rs));
         cur = rs.getInt("cur");
     }
}




Reply via email to