----- Original message ----- > > > 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. > > Not sure I follow. Currently you do "new A(rs)" which internally calls > "A.check(rs)" and I was suggesting you call A.check(rs) directly so > avoiding the need to create an A just for validation purposes, and which > is subsequently discarded. > > David >
A is also created to allow B to access its upper and lower limit fields, in this case to ensure that the integer cur is between these limits. Intra class invariants. Cheers, Peter. > > > > > > > > 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"); > > > > > > } > > > > > > } > > > > > > > > > > > > > > > > > >