Java is a safe language, but without action, security is not guaranteed. It is assumed that the client of the class will do its best to break the constraints of the class, so the program must be designed in a protective manner.
Consider the following class, which claims to represent an immutable period of time:
Importjava.util.Date; Public Final classPeriod {Private FinalDate start; Private FinalDate end; PublicPeriod (date start, date end) {if(Start.compareto (end) > 0) Throw NewIllegalArgumentException (start + "after" +end); This. Start =start; This. end =end; } PublicDate Start () {returnstart; } PublicDate End () {returnend; }}
Because date itself is mutable, it is easy to violate the constraint that the start time cannot be after the end time.
NewNew New Period (start, end); End.setyear (78);//change the termination time, Constraint conditions for a broken class
In order to protect the internal information of the period instance from being destroyed, a protective copy of each variable parameter of the constructor is used, the Backup object as the component of the period instance, and the parameters passed in by the client are not used.
Public Period (date start, date end) { thisnew date (Start.gettime ()); This New Date (End.gettime ()); if (this. Start.compareto (this. end) > 0) Throw New IllegalArgumentException (start + "after" + end);}
Protective copy before the parameter validity check, this can avoid in the multi-threaded environment, after the parameter validity passes, changes the parameter from another thread, causes the parameter validity detection to fail.
The reason for a protected copy without using the Clone method is that date is not final, and it is not guaranteed that the Clone method will return a Date object, and it may return an instance of a malicious non-Nobuko class.
After doing the above work, it is still possible to change the period instance because its access method provides access to its variable internal members:
NewNew New Period (start, end);p. End (). Setyear (78);
Change the access method to return a protected copy of the mutable internal domain:
Public Date Start () { returnnew Date (Start.gettime ());} Public Date End () { returnnew Date (End.gettime ());}
With the new constructor and the new access method, period is truly immutable, no matter how malicious and unqualified the programmer is, there is absolutely no violation of the constraint that the cycle start time is greater than the end time. The access method differs from the constructor in that it allows the Clone method to be used when a protective copy is made, because the object of the period internal date must be date and cannot be an untrusted subclass.
Whenever possible, an immutable object should be used as an internal component of the object, so you don't have to worry about a protective copy. In the period example, using the basic type returned by Date.gettime () as the internal time notation, there is no need for a protective copy.
If a class has a mutable component that gets or returns a client from the client, the class must copy the components in a protective manner, and if the copy cost is limited and the class trust caller does not modify the internal components, it is also possible to do so without a protective copy, and the documentation for the class must clearly state this.
39th: A protective copy if necessary