]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_2_1-src/src/com/ibm/icu/util/Freezable.java
icu4jsrc
[Dictionary.git] / jars / icu4j-4_2_1-src / src / com / ibm / icu / util / Freezable.java
1 /*\r
2  ******************************************************************************\r
3  * Copyright (C) 200-2007, International Business Machines Corporation and    *\r
4  * others. All Rights Reserved.                                               *\r
5  ******************************************************************************\r
6 */\r
7 package com.ibm.icu.util;\r
8 \r
9 /**\r
10  * Provides a flexible mechanism for controlling access, without requiring that\r
11  * a class be immutable. Once locked, an object can never be unlocked, so it is\r
12  * thread-safe from that point onward. The implementation of both methods must\r
13  * be synchronized. Once the object has been locked, it must guarantee that no\r
14  * changes can be made to it. Any attempt to alter it must raise an\r
15  * UnsupportedOperationException exception. This means that when the object\r
16  * returns internal objects, or if anyone has references to those internal\r
17  * objects, that those internal objects must either be immutable, or must also\r
18  * raise exceptions if any attempt to modify them is made. Of course, the object\r
19  * can return clones of internal objects, since those are safe.\r
20  * <h2>Background</h2>\r
21  * <p>\r
22  * There are often times when you need objects to be objects 'safe', so that\r
23  * they can't be modified. Examples are when objects need to be thread-safe, or\r
24  * in writing robust code, or in caches. If you are only creating your own\r
25  * objects, you can guarantee this, of course -- but only if you don't make a\r
26  * mistake. If you have objects handed into you, or are creating objects using\r
27  * others handed into you, it is a different story. It all comes down to whether\r
28  * you want to take the Blanche Dubois approach (&quot;depend on the kindness of\r
29  * strangers&quot;) or the Andy Grove approach (&quot;Only the Paranoid\r
30  * Survive&quot;).\r
31  * </p>\r
32  * <p>\r
33  * For example, suppose we have a simple class:\r
34  * </p>\r
35  * \r
36  * <pre>\r
37  * public class A {\r
38  *      protected Collection b;\r
39  * \r
40  *      protected Collection c;\r
41  * \r
42  *      public Collection get_b() {\r
43  *              return b;\r
44  *      }\r
45  * \r
46  *      public Collection get_c() {\r
47  *              return c;\r
48  *      }\r
49  * \r
50  *      public A(Collection new_b, Collection new_c) {\r
51  *              b = new_b;\r
52  *              c = new_c;\r
53  *      }\r
54  * }\r
55  * </pre>\r
56  * \r
57  * <p>\r
58  * Since the class doesn't have any setters, someone might think that it is\r
59  * immutable. You know where this is leading, of course; this class is unsafe in\r
60  * a number of ways. The following illustrates that.\r
61  * </p>\r
62  * \r
63  * <pre>\r
64  *  public test1(SupposedlyImmutableClass x, SafeStorage y) {\r
65  *   &lt;font color=&quot;#0000FF&quot;&gt;    &lt;b&gt;// unsafe getter&lt;/b&gt;\r
66  *   &lt;/font&gt;    A a = x.getA();\r
67  *   Collection col = a.get_b();\r
68  *   col.add(something);&lt;font color=&quot;#0000FF&quot;&gt; // a has now been changed, and x too\r
69  *   &lt;/font&gt;\r
70  *   &lt;font color=&quot;#0000FF&quot;&gt;&lt;b&gt;// unsafe constructor&lt;/b&gt;&lt;/font&gt;\r
71  *   a = new A(col, col);\r
72  *   y.store(a);\r
73  *   col.add(something);&lt;font color=&quot;#0000FF&quot;&gt; // a has now been changed, and y too\r
74  *  \r
75  *   &lt;/font&gt;}\r
76  * </pre>\r
77  * \r
78  * <p>\r
79  * There are a few different techniques for having safe classes.\r
80  * </p>\r
81  * <ol>\r
82  * <li>Const objects. In C++, you can declare parameters const.</li>\r
83  * <li>Immutable wrappers. For example, you can put a collection in an\r
84  * immutable wrapper.</li>\r
85  * <li>Always-Immutable objects. Java uses this approach, with a few\r
86  * variations. Examples:\r
87  * <ol>\r
88  * <li>Simple. Once a Color is created (eg from R, G, and B integers) it is\r
89  * immutable.</li>\r
90  * <li>Builder Class. There is a separate 'builder' class. For example,\r
91  * modifiable Strings are created using StringBuffer (which doesn't have the\r
92  * full String API available). Once you want an immutable form, you create one\r
93  * with toString().</li>\r
94  * <li>Primitives. These are always safe, since they are copied on input/output\r
95  * from methods.</li>\r
96  * </ol>\r
97  * </li>\r
98  * <li>Cloning. Where you need an object to be safe, you clone it.</li>\r
99  * </ol>\r
100  * <p>\r
101  * There are advantages and disadvantages of each of these.\r
102  * </p>\r
103  * <ol>\r
104  * <li>Const provides a certain level of protection, but since const can be and\r
105  * is often cast away, it only protects against most inadvertent mistakes. It\r
106  * also offers no threading protection, since anyone who has a pointer to the\r
107  * (unconst) object in another thread can mess you up.</li>\r
108  * <li>Immutable wrappers are safer than const in that the constness can't be\r
109  * cast away. But other than that they have all the same problems: not safe if\r
110  * someone else keeps hold of the original object, or if any of the objects\r
111  * returned by the class are mutable.</li>\r
112  * <li>Always-Immutable Objects are safe, but usage can require excessive\r
113  * object creation.</li>\r
114  * <li>Cloning is only safe if the object truly has a 'safe' clone; defined as\r
115  * one that <i>ensures that no change to the clone affects the original</i>.\r
116  * Unfortunately, many objects don't have a 'safe' clone, and always cloning can\r
117  * require excessive object creation.</li>\r
118  * </ol>\r
119  * <h2>Freezable Model</h2>\r
120  * <p>\r
121  * The <code>Freezable</code> model supplements these choices by giving you\r
122  * the ability to build up an object by calling various methods, then when it is\r
123  * in a final state, you can <i>make</i> it immutable. Once immutable, an\r
124  * object cannot <i>ever </i>be modified, and is completely thread-safe: that\r
125  * is, multiple threads can have references to it without any synchronization.\r
126  * If someone needs a mutable version of an object, they can use\r
127  * <code>cloneAsThawed()</code>, and modify the copy. This provides a simple,\r
128  * effective mechanism for safe classes in circumstances where the alternatives\r
129  * are insufficient or clumsy. (If an object is shared before it is immutable,\r
130  * then it is the responsibility of each thread to mutex its usage (as with\r
131  * other objects).)\r
132  * </p>\r
133  * <p>\r
134  * Here is what needs to be done to implement this interface, depending on the\r
135  * type of the object.\r
136  * </p>\r
137  * <h3><b>Immutable Objects</b></h3>\r
138  * <p>\r
139  * These are the easiest. You just use the interface to reflect that, by adding\r
140  * the following:\r
141  * </p>\r
142  * \r
143  * <pre>\r
144  *  public class A implements Freezable {\r
145  *   ...\r
146  *   public final boolean isFrozen() {return true;}\r
147  *   public final Object freeze() {return this;}\r
148  *   public final Object cloneAsThawed() { return this; }\r
149  *   }\r
150  * </pre>\r
151  * \r
152  * <p>\r
153  * These can be final methods because subclasses of immutable objects must\r
154  * themselves be immutable. (Note: <code>freeze</code> is returning\r
155  * <code>this</code> for chaining.)\r
156  * </p>\r
157  * <h3><b>Mutable Objects</b></h3>\r
158  * <p>\r
159  * Add a protected 'flagging' field:\r
160  * </p>\r
161  * \r
162  * <pre>\r
163  * protected boolean immutable;\r
164  * </pre>\r
165  * \r
166  * <p>\r
167  * Add the following methods:\r
168  * </p>\r
169  * \r
170  * <pre>\r
171  * public final boolean isFrozen() {\r
172  *      return frozen;\r
173  * };\r
174  * \r
175  * public Object freeze() {\r
176  *      frozen = true;\r
177  *      return this;\r
178  * }\r
179  * </pre>\r
180  * \r
181  * <p>\r
182  * Add a <code>cloneAsThawed()</code> method following the normal pattern for\r
183  * <code>clone()</code>, except that <code>frozen=false</code> in the new\r
184  * clone.\r
185  * </p>\r
186  * <p>\r
187  * Then take the setters (that is, any method that can change the internal state\r
188  * of the object), and add the following as the first statement:\r
189  * </p>\r
190  * \r
191  * <pre>\r
192  * if (isFrozen()) {\r
193  *      throw new UnsupportedOperationException(&quot;Attempt to modify frozen object&quot;);\r
194  * }\r
195  * </pre>\r
196  * \r
197  * <h4><b>Subclassing</b></h4>\r
198  * <p>\r
199  * Any subclass of a <code>Freezable</code> will just use its superclass's\r
200  * flagging field. It must override <code>freeze()</code> and\r
201  * <code>cloneAsThawed()</code> to call the superclass, but normally does not\r
202  * override <code>isFrozen()</code>. It must then just pay attention to its\r
203  * own getters, setters and fields.\r
204  * </p>\r
205  * <h4><b>Internal Caches</b></h4>\r
206  * <p>\r
207  * Internal caches are cases where the object is logically unmodified, but\r
208  * internal state of the object changes. For example, there are const C++\r
209  * functions that cast away the const on the &quot;this&quot; pointer in order\r
210  * to modify an object cache. These cases are handled by mutexing the internal\r
211  * cache to ensure thread-safety. For example, suppose that UnicodeSet had an\r
212  * internal marker to the last code point accessed. In this case, the field is\r
213  * not externally visible, so the only thing you need to do is to synchronize\r
214  * the field for thread safety.\r
215  * </p>\r
216  * <h4>Unsafe Internal Access</h4>\r
217  * <p>\r
218  * Internal fields are called <i>safe</i> if they are either\r
219  * <code>frozen</code> or immutable (such as String or primitives). If you've\r
220  * never allowed internal access to these, then you are all done. For example,\r
221  * converting UnicodeSet to be <code>Freezable</code> is just accomplished\r
222  * with the above steps. But remember that you <i><b>have</b></i> allowed\r
223  * access to unsafe internals if you have any code like the following, in a\r
224  * getter, setter, or constructor:\r
225  * </p>\r
226  * \r
227  * <pre>\r
228  * Collection getStuff() {\r
229  *      return stuff;\r
230  * } // caller could keep reference &amp; modify\r
231  * \r
232  * void setStuff(Collection x) {\r
233  *      stuff = x;\r
234  * } // caller could keep reference &amp; modify\r
235  * \r
236  * MyClass(Collection x) {\r
237  *      stuff = x;\r
238  * } // caller could keep reference &amp; modify\r
239  * </pre>\r
240  * \r
241  * <p>\r
242  * These also illustrated in the code sample in <b>Background</b> above.\r
243  * </p>\r
244  * <p>\r
245  * To deal with unsafe internals, the simplest course of action is to do the\r
246  * work in the <code>\r
247  freeze()</code> function. Just make all of your internal\r
248  * fields frozen, and set the frozen flag. Any subsequent getter/setter will\r
249  * work properly. Here is an example:\r
250  * </p>\r
251  * \r
252  * <pre>\r
253  * public Object freeze() {\r
254  *      if (!frozen) {\r
255  *              foo.freeze();\r
256  *              frozen = true;\r
257  *      }\r
258  *      return this;\r
259  * }\r
260  * </pre>\r
261  * \r
262  * <p>\r
263  * If the field is a <code>Collection</code> or <code>Map</code>, then to\r
264  * make it frozen you have two choices. If you have never allowed access to the\r
265  * collection from outside your object, then just wrap it to prevent future\r
266  * modification.\r
267  * </p>\r
268  * \r
269  * <pre>\r
270  * zone_to_country = Collections.unmodifiableMap(zone_to_country);\r
271  * </pre>\r
272  * \r
273  * <p>\r
274  * If you have <i>ever</i> allowed access, then do a <code>clone()</code>\r
275  * before wrapping it.\r
276  * </p>\r
277  * \r
278  * <pre>\r
279  * zone_to_country = Collections.unmodifiableMap(zone_to_country.clone());\r
280  * </pre>\r
281  * \r
282  * <p>\r
283  * If a collection <i>(or any other container of objects)</i> itself can\r
284  * contain mutable objects, then for a safe clone you need to recurse through it\r
285  * to make the entire collection immutable. The recursing code should pick the\r
286  * most specific collection available, to avoid the necessity of later\r
287  * downcasing.\r
288  * </p>\r
289  * <blockquote>\r
290  * <p>\r
291  * <b>Note: </b>An annoying flaw in Java is that the generic collections, like\r
292  * <code>Map</code> or <code>Set</code>, don't have a <code>clone()</code>\r
293  * operation. When you don't know the type of the collection, the simplest\r
294  * course is to just create a new collection:\r
295  * </p>\r
296  * \r
297  * <pre>\r
298  * zone_to_country = Collections.unmodifiableMap(new HashMap(zone_to_country));\r
299  * </pre>\r
300  * \r
301  * </blockquote>\r
302  * @stable ICU 3.8\r
303  */\r
304 public interface Freezable extends Cloneable {\r
305     /**\r
306      * Determines whether the object has been locked or not.\r
307      * @stable ICU 3.8\r
308      */\r
309     public boolean isFrozen();\r
310 \r
311     /**\r
312      * Locks the object.\r
313      * @return the object itself.\r
314      * @stable ICU 3.8\r
315      */\r
316     public Object freeze();\r
317 \r
318     /**\r
319      * Provides for the clone operation. Any clone is initially unlocked.\r
320      * @stable ICU 3.8\r
321      */\r
322     public Object cloneAsThawed();\r
323 }\r