KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > lang > builder > EqualsBuilder


1 /*
2  * Copyright 2002-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.lang.builder;
17
18 import java.lang.reflect.AccessibleObject JavaDoc;
19 import java.lang.reflect.Field JavaDoc;
20 import java.lang.reflect.Modifier JavaDoc;
21
22 /**
23  * <p>Assists in implementing {@link Object#equals(Object)} methods.</p>
24  *
25  * <p> This class provides methods to build a good equals method for any
26  * class. It follows rules laid out in
27  * <a HREF="http://java.sun.com/docs/books/effective/index.html">Effective Java</a>
28  * , by Joshua Bloch. In particular the rule for comparing <code>doubles</code>,
29  * <code>floats</code>, and arrays can be tricky. Also, making sure that
30  * <code>equals()</code> and <code>hashCode()</code> are consistent can be
31  * difficult.</p>
32  *
33  * <p>Two Objects that compare as equals must generate the same hash code,
34  * but two Objects with the same hash code do not have to be equal.</p>
35  *
36  * <p>All relevant fields should be included in the calculation of equals.
37  * Derived fields may be ignored. In particular, any field used in
38  * generating a hash code must be used in the equals method, and vice
39  * versa.</p>
40  *
41  * <p>Typical use for the code is as follows:</p>
42  * <pre>
43  * public boolean equals(Object obj) {
44  * if (obj instanceof MyClass == false) {
45  * return false;
46  * }
47  * if (this == obj) {
48  * return true;
49  * }
50  * MyClass rhs = (MyClass) obj;
51  * return new EqualsBuilder()
52  * .appendSuper(super.equals(obj))
53  * .append(field1, rhs.field1)
54  * .append(field2, rhs.field2)
55  * .append(field3, rhs.field3)
56  * .isEquals();
57  * }
58  * </pre>
59  *
60  * <p> Alternatively, there is a method that uses reflection to determine
61  * the fields to test. Because these fields are usually private, the method,
62  * <code>reflectionEquals</code>, uses <code>AccessibleObject.setAccessible</code> to
63  * change the visibility of the fields. This will fail under a security
64  * manager, unless the appropriate permissions are set up correctly. It is
65  * also slower than testing explicitly.</p>
66  *
67  * <p> A typical invocation for this method would look like:</p>
68  * <pre>
69  * public boolean equals(Object obj) {
70  * return EqualsBuilder.reflectionEquals(this, obj);
71  * }
72  * </pre>
73  *
74  * @author <a HREF="mailto:steve.downey@netfolio.com">Steve Downey</a>
75  * @author Stephen Colebourne
76  * @author Gary Gregory
77  * @author Pete Gieser
78  * @author Arun Mammen Thomas
79  * @since 1.0
80  * @version $Id: EqualsBuilder.java 161243 2005-04-14 04:30:28Z ggregory $
81  */

82 public class EqualsBuilder {
83     
84     /**
85      * If the fields tested are equals.
86      * The default value is <code>true</code>.
87      */

88     private boolean isEquals = true;
89
90     /**
91      * <p>Constructor for EqualsBuilder.</p>
92      *
93      * <p>Starts off assuming that equals is <code>true</code>.</p>
94      * @see Object#equals(Object)
95      */

96     public EqualsBuilder() {
97         // do nothing for now.
98
}
99
100     //-------------------------------------------------------------------------
101

102     /**
103      * <p>This method uses reflection to determine if the two <code>Object</code>s
104      * are equal.</p>
105      *
106      * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
107      * fields. This means that it will throw a security exception if run under
108      * a security manager, if the permissions are not set up correctly. It is also
109      * not as efficient as testing explicitly.</p>
110      *
111      * <p>Transient members will be not be tested, as they are likely derived
112      * fields, and not part of the value of the Object.</p>
113      *
114      * <p>Static fields will not be tested. Superclass fields will be included.</p>
115      *
116      * @param lhs <code>this</code> object
117      * @param rhs the other object
118      * @return <code>true</code> if the two Objects have tested equals.
119      */

120     public static boolean reflectionEquals(Object JavaDoc lhs, Object JavaDoc rhs) {
121         return reflectionEquals(lhs, rhs, false, null);
122     }
123
124     /**
125      * <p>This method uses reflection to determine if the two <code>Object</code>s
126      * are equal.</p>
127      *
128      * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
129      * fields. This means that it will throw a security exception if run under
130      * a security manager, if the permissions are not set up correctly. It is also
131      * not as efficient as testing explicitly.</p>
132      *
133      * <p>If the TestTransients parameter is set to <code>true</code>, transient
134      * members will be tested, otherwise they are ignored, as they are likely
135      * derived fields, and not part of the value of the <code>Object</code>.</p>
136      *
137      * <p>Static fields will not be tested. Superclass fields will be included.</p>
138      *
139      * @param lhs <code>this</code> object
140      * @param rhs the other object
141      * @param testTransients whether to include transient fields
142      * @return <code>true</code> if the two Objects have tested equals.
143      */

144     public static boolean reflectionEquals(Object JavaDoc lhs, Object JavaDoc rhs, boolean testTransients) {
145         return reflectionEquals(lhs, rhs, testTransients, null);
146     }
147
148     /**
149      * <p>This method uses reflection to determine if the two <code>Object</code>s
150      * are equal.</p>
151      *
152      * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
153      * fields. This means that it will throw a security exception if run under
154      * a security manager, if the permissions are not set up correctly. It is also
155      * not as efficient as testing explicitly.</p>
156      *
157      * <p>If the testTransients parameter is set to <code>true</code>, transient
158      * members will be tested, otherwise they are ignored, as they are likely
159      * derived fields, and not part of the value of the <code>Object</code>.</p>
160      *
161      * <p>Static fields will not be included. Superclass fields will be appended
162      * up to and including the specified superclass. A null superclass is treated
163      * as java.lang.Object.</p>
164      *
165      * @param lhs <code>this</code> object
166      * @param rhs the other object
167      * @param testTransients whether to include transient fields
168      * @param reflectUpToClass the superclass to reflect up to (inclusive),
169      * may be <code>null</code>
170      * @return <code>true</code> if the two Objects have tested equals.
171      * @since 2.0
172      */

173     public static boolean reflectionEquals(Object JavaDoc lhs, Object JavaDoc rhs, boolean testTransients, Class JavaDoc reflectUpToClass) {
174         if (lhs == rhs) {
175             return true;
176         }
177         if (lhs == null || rhs == null) {
178             return false;
179         }
180         // Find the leaf class since there may be transients in the leaf
181
// class or in classes between the leaf and root.
182
// If we are not testing transients or a subclass has no ivars,
183
// then a subclass can test equals to a superclass.
184
Class JavaDoc lhsClass = lhs.getClass();
185         Class JavaDoc rhsClass = rhs.getClass();
186         Class JavaDoc testClass;
187         if (lhsClass.isInstance(rhs)) {
188             testClass = lhsClass;
189             if (!rhsClass.isInstance(lhs)) {
190                 // rhsClass is a subclass of lhsClass
191
testClass = rhsClass;
192             }
193         } else if (rhsClass.isInstance(lhs)) {
194             testClass = rhsClass;
195             if (!lhsClass.isInstance(rhs)) {
196                 // lhsClass is a subclass of rhsClass
197
testClass = lhsClass;
198             }
199         } else {
200             // The two classes are not related.
201
return false;
202         }
203         EqualsBuilder equalsBuilder = new EqualsBuilder();
204         try {
205             reflectionAppend(lhs, rhs, testClass, equalsBuilder, testTransients);
206             while (testClass.getSuperclass() != null && testClass != reflectUpToClass) {
207                 testClass = testClass.getSuperclass();
208                 reflectionAppend(lhs, rhs, testClass, equalsBuilder, testTransients);
209             }
210         } catch (IllegalArgumentException JavaDoc e) {
211             // In this case, we tried to test a subclass vs. a superclass and
212
// the subclass has ivars or the ivars are transient and
213
// we are testing transients.
214
// If a subclass has ivars that we are trying to test them, we get an
215
// exception and we know that the objects are not equal.
216
return false;
217         }
218         return equalsBuilder.isEquals();
219     }
220
221     /**
222      * <p>Appends the fields and values defined by the given object of the
223      * given Class.</p>
224      *
225      * @param lhs the left hand object
226      * @param rhs the right hand object
227      * @param clazz the class to append details of
228      * @param builder the builder to append to
229      * @param useTransients whether to test transient fields
230      */

231     private static void reflectionAppend(
232         Object JavaDoc lhs,
233         Object JavaDoc rhs,
234         Class JavaDoc clazz,
235         EqualsBuilder builder,
236         boolean useTransients) {
237         Field JavaDoc[] fields = clazz.getDeclaredFields();
238         AccessibleObject.setAccessible(fields, true);
239         for (int i = 0; i < fields.length && builder.isEquals; i++) {
240             Field JavaDoc f = fields[i];
241             if ((f.getName().indexOf('$') == -1)
242                 && (useTransients || !Modifier.isTransient(f.getModifiers()))
243                 && (!Modifier.isStatic(f.getModifiers()))) {
244                 try {
245                     builder.append(f.get(lhs), f.get(rhs));
246                 } catch (IllegalAccessException JavaDoc e) {
247                     //this can't happen. Would get a Security exception instead
248
//throw a runtime exception in case the impossible happens.
249
throw new InternalError JavaDoc("Unexpected IllegalAccessException");
250                 }
251             }
252         }
253     }
254
255     //-------------------------------------------------------------------------
256

257     /**
258      * <p>Adds the result of <code>super.equals()</code> to this builder.</p>
259      *
260      * @param superEquals the result of calling <code>super.equals()</code>
261      * @return EqualsBuilder - used to chain calls.
262      * @since 2.0
263      */

264     public EqualsBuilder appendSuper(boolean superEquals) {
265         if (isEquals == false) {
266             return this;
267         }
268         isEquals = superEquals;
269         return this;
270     }
271
272     //-------------------------------------------------------------------------
273

274     /**
275      * <p>Test if two <code>Object</code>s are equal using their
276      * <code>equals</code> method.</p>
277      *
278      * @param lhs the left hand object
279      * @param rhs the right hand object
280      * @return EqualsBuilder - used to chain calls.
281      */

282     public EqualsBuilder append(Object JavaDoc lhs, Object JavaDoc rhs) {
283         if (isEquals == false) {
284             return this;
285         }
286         if (lhs == rhs) {
287             return this;
288         }
289         if (lhs == null || rhs == null) {
290             this.setEquals(false);
291             return this;
292         }
293         Class JavaDoc lhsClass = lhs.getClass();
294         if (!lhsClass.isArray()) {
295             // The simple case, not an array, just test the element
296
isEquals = lhs.equals(rhs);
297         } else if (lhs.getClass() != rhs.getClass()) {
298             // Here when we compare different dimensions, for example: a boolean[][] to a boolean[]
299
this.setEquals(false);
300         }
301         // 'Switch' on type of array, to dispatch to the correct handler
302
// This handles multi dimensional arrays of the same depth
303
else if (lhs instanceof long[]) {
304             append((long[]) lhs, (long[]) rhs);
305         } else if (lhs instanceof int[]) {
306             append((int[]) lhs, (int[]) rhs);
307         } else if (lhs instanceof short[]) {
308             append((short[]) lhs, (short[]) rhs);
309         } else if (lhs instanceof char[]) {
310             append((char[]) lhs, (char[]) rhs);
311         } else if (lhs instanceof byte[]) {
312             append((byte[]) lhs, (byte[]) rhs);
313         } else if (lhs instanceof double[]) {
314             append((double[]) lhs, (double[]) rhs);
315         } else if (lhs instanceof float[]) {
316             append((float[]) lhs, (float[]) rhs);
317         } else if (lhs instanceof boolean[]) {
318             append((boolean[]) lhs, (boolean[]) rhs);
319         } else {
320             // Not an array of primitives
321
append((Object JavaDoc[]) lhs, (Object JavaDoc[]) rhs);
322         }
323         return this;
324     }
325
326     /**
327      * <p>
328      * Test if two <code>long</code> s are equal.
329      * </p>
330      *
331      * @param lhs
332      * the left hand <code>long</code>
333      * @param rhs
334      * the right hand <code>long</code>
335      * @return EqualsBuilder - used to chain calls.
336      */

337     public EqualsBuilder append(long lhs, long rhs) {
338         if (isEquals == false) {
339             return this;
340         }
341         isEquals = (lhs == rhs);
342         return this;
343     }
344
345     /**
346      * <p>Test if two <code>int</code>s are equal.</p>
347      *
348      * @param lhs the left hand <code>int</code>
349      * @param rhs the right hand <code>int</code>
350      * @return EqualsBuilder - used to chain calls.
351      */

352     public EqualsBuilder append(int lhs, int rhs) {
353         if (isEquals == false) {
354             return this;
355         }
356         isEquals = (lhs == rhs);
357         return this;
358     }
359
360     /**
361      * <p>Test if two <code>short</code>s are equal.</p>
362      *
363      * @param lhs the left hand <code>short</code>
364      * @param rhs the right hand <code>short</code>
365      * @return EqualsBuilder - used to chain calls.
366      */

367     public EqualsBuilder append(short lhs, short rhs) {
368         if (isEquals == false) {
369             return this;
370         }
371         isEquals = (lhs == rhs);
372         return this;
373     }
374
375     /**
376      * <p>Test if two <code>char</code>s are equal.</p>
377      *
378      * @param lhs the left hand <code>char</code>
379      * @param rhs the right hand <code>char</code>
380      * @return EqualsBuilder - used to chain calls.
381      */

382     public EqualsBuilder append(char lhs, char rhs) {
383         if (isEquals == false) {
384             return this;
385         }
386         isEquals = (lhs == rhs);
387         return this;
388     }
389
390     /**
391      * <p>Test if two <code>byte</code>s are equal.</p>
392      *
393      * @param lhs the left hand <code>byte</code>
394      * @param rhs the right hand <code>byte</code>
395      * @return EqualsBuilder - used to chain calls.
396      */

397     public EqualsBuilder append(byte lhs, byte rhs) {
398         if (isEquals == false) {
399             return this;
400         }
401         isEquals = (lhs == rhs);
402         return this;
403     }
404
405     /**
406      * <p>Test if two <code>double</code>s are equal by testing that the
407      * pattern of bits returned by <code>doubleToLong</code> are equal.</p>
408      *
409      * <p>This handles NaNs, Infinities, and <code>-0.0</code>.</p>
410      *
411      * <p>It is compatible with the hash code generated by
412      * <code>HashCodeBuilder</code>.</p>
413      *
414      * @param lhs the left hand <code>double</code>
415      * @param rhs the right hand <code>double</code>
416      * @return EqualsBuilder - used to chain calls.
417      */

418     public EqualsBuilder append(double lhs, double rhs) {
419         if (isEquals == false) {
420             return this;
421         }
422         return append(Double.doubleToLongBits(lhs), Double.doubleToLongBits(rhs));
423     }
424
425     /**
426      * <p>Test if two <code>float</code>s are equal byt testing that the
427      * pattern of bits returned by doubleToLong are equal.</p>
428      *
429      * <p>This handles NaNs, Infinities, and <code>-0.0</code>.</p>
430      *
431      * <p>It is compatible with the hash code generated by
432      * <code>HashCodeBuilder</code>.</p>
433      *
434      * @param lhs the left hand <code>float</code>
435      * @param rhs the right hand <code>float</code>
436      * @return EqualsBuilder - used to chain calls.
437      */

438     public EqualsBuilder append(float lhs, float rhs) {
439         if (isEquals == false) {
440             return this;
441         }
442         return append(Float.floatToIntBits(lhs), Float.floatToIntBits(rhs));
443     }
444
445     /**
446      * <p>Test if two <code>booleans</code>s are equal.</p>
447      *
448      * @param lhs the left hand <code>boolean</code>
449      * @param rhs the right hand <code>boolean</code>
450      * @return EqualsBuilder - used to chain calls.
451       */

452     public EqualsBuilder append(boolean lhs, boolean rhs) {
453         if (isEquals == false) {
454             return this;
455         }
456         isEquals = (lhs == rhs);
457         return this;
458     }
459
460     /**
461      * <p>Performs a deep comparison of two <code>Object</code> arrays.</p>
462      *
463      * <p>This also will be called for the top level of
464      * multi-dimensional, ragged, and multi-typed arrays.</p>
465      *
466      * @param lhs the left hand <code>Object[]</code>
467      * @param rhs the right hand <code>Object[]</code>
468      * @return EqualsBuilder - used to chain calls.
469      */

470     public EqualsBuilder append(Object JavaDoc[] lhs, Object JavaDoc[] rhs) {
471         if (isEquals == false) {
472             return this;
473         }
474         if (lhs == rhs) {
475             return this;
476         }
477         if (lhs == null || rhs == null) {
478             this.setEquals(false);
479             return this;
480         }
481         if (lhs.length != rhs.length) {
482             this.setEquals(false);
483             return this;
484         }
485         for (int i = 0; i < lhs.length && isEquals; ++i) {
486             append(lhs[i], rhs[i]);
487         }
488         return this;
489     }
490
491     /**
492      * <p>Deep comparison of array of <code>long</code>. Length and all
493      * values are compared.</p>
494      *
495      * <p>The method {@link #append(long, long)} is used.</p>
496      *
497      * @param lhs the left hand <code>long[]</code>
498      * @param rhs the right hand <code>long[]</code>
499      * @return EqualsBuilder - used to chain calls.
500      */

501     public EqualsBuilder append(long[] lhs, long[] rhs) {
502         if (isEquals == false) {
503             return this;
504         }
505         if (lhs == rhs) {
506             return this;
507         }
508         if (lhs == null || rhs == null) {
509             this.setEquals(false);
510             return this;
511         }
512         if (lhs.length != rhs.length) {
513             this.setEquals(false);
514             return this;
515         }
516         for (int i = 0; i < lhs.length && isEquals; ++i) {
517             append(lhs[i], rhs[i]);
518         }
519         return this;
520     }
521
522     /**
523      * <p>Deep comparison of array of <code>int</code>. Length and all
524      * values are compared.</p>
525      *
526      * <p>The method {@link #append(int, int)} is used.</p>
527      *
528      * @param lhs the left hand <code>int[]</code>
529      * @param rhs the right hand <code>int[]</code>
530      * @return EqualsBuilder - used to chain calls.
531      */

532     public EqualsBuilder append(int[] lhs, int[] rhs) {
533         if (isEquals == false) {
534             return this;
535         }
536         if (lhs == rhs) {
537             return this;
538         }
539         if (lhs == null || rhs == null) {
540             this.setEquals(false);
541             return this;
542         }
543         if (lhs.length != rhs.length) {
544             this.setEquals(false);
545             return this;
546         }
547         for (int i = 0; i < lhs.length && isEquals; ++i) {
548             append(lhs[i], rhs[i]);
549         }
550         return this;
551     }
552
553     /**
554      * <p>Deep comparison of array of <code>short</code>. Length and all
555      * values are compared.</p>
556      *
557      * <p>The method {@link #append(short, short)} is used.</p>
558      *
559      * @param lhs the left hand <code>short[]</code>
560      * @param rhs the right hand <code>short[]</code>
561      * @return EqualsBuilder - used to chain calls.
562      */

563     public EqualsBuilder append(short[] lhs, short[] rhs) {
564         if (isEquals == false) {
565             return this;
566         }
567         if (lhs == rhs) {
568             return this;
569         }
570         if (lhs == null || rhs == null) {
571             this.setEquals(false);
572             return this;
573         }
574         if (lhs.length != rhs.length) {
575             this.setEquals(false);
576             return this;
577         }
578         for (int i = 0; i < lhs.length && isEquals; ++i) {
579             append(lhs[i], rhs[i]);
580         }
581         return this;
582     }
583
584     /**
585      * <p>Deep comparison of array of <code>char</code>. Length and all
586      * values are compared.</p>
587      *
588      * <p>The method {@link #append(char, char)} is used.</p>
589      *
590      * @param lhs the left hand <code>char[]</code>
591      * @param rhs the right hand <code>char[]</code>
592      * @return EqualsBuilder - used to chain calls.
593      */

594     public EqualsBuilder append(char[] lhs, char[] rhs) {
595         if (isEquals == false) {
596             return this;
597         }
598         if (lhs == rhs) {
599             return this;
600         }
601         if (lhs == null || rhs == null) {
602             this.setEquals(false);
603             return this;
604         }
605         if (lhs.length != rhs.length) {
606             this.setEquals(false);
607             return this;
608         }
609         for (int i = 0; i < lhs.length && isEquals; ++i) {
610             append(lhs[i], rhs[i]);
611         }
612         return this;
613     }
614
615     /**
616      * <p>Deep comparison of array of <code>byte</code>. Length and all
617      * values are compared.</p>
618      *
619      * <p>The method {@link #append(byte, byte)} is used.</p>
620      *
621      * @param lhs the left hand <code>byte[]</code>
622      * @param rhs the right hand <code>byte[]</code>
623      * @return EqualsBuilder - used to chain calls.
624      */

625     public EqualsBuilder append(byte[] lhs, byte[] rhs) {
626         if (isEquals == false) {
627             return this;
628         }
629         if (lhs == rhs) {
630             return this;
631         }
632         if (lhs == null || rhs == null) {
633             this.setEquals(false);
634             return this;
635         }
636         if (lhs.length != rhs.length) {
637             this.setEquals(false);
638             return this;
639         }
640         for (int i = 0; i < lhs.length && isEquals; ++i) {
641             append(lhs[i], rhs[i]);
642         }
643         return this;
644     }
645
646     /**
647      * <p>Deep comparison of array of <code>double</code>. Length and all
648      * values are compared.</p>
649      *
650      * <p>The method {@link #append(double, double)} is used.</p>
651      *
652      * @param lhs the left hand <code>double[]</code>
653      * @param rhs the right hand <code>double[]</code>
654      * @return EqualsBuilder - used to chain calls.
655      */

656     public EqualsBuilder append(double[] lhs, double[] rhs) {
657         if (isEquals == false) {
658             return this;
659         }
660         if (lhs == rhs) {
661             return this;
662         }
663         if (lhs == null || rhs == null) {
664             this.setEquals(false);
665             return this;
666         }
667         if (lhs.length != rhs.length) {
668             this.setEquals(false);
669             return this;
670         }
671         for (int i = 0; i < lhs.length && isEquals; ++i) {
672             append(lhs[i], rhs[i]);
673         }
674         return this;
675     }
676
677     /**
678      * <p>Deep comparison of array of <code>float</code>. Length and all
679      * values are compared.</p>
680      *
681      * <p>The method {@link #append(float, float)} is used.</p>
682      *
683      * @param lhs the left hand <code>float[]</code>
684      * @param rhs the right hand <code>float[]</code>
685      * @return EqualsBuilder - used to chain calls.
686      */

687     public EqualsBuilder append(float[] lhs, float[] rhs) {
688         if (isEquals == false) {
689             return this;
690         }
691         if (lhs == rhs) {
692             return this;
693         }
694         if (lhs == null || rhs == null) {
695             this.setEquals(false);
696             return this;
697         }
698         if (lhs.length != rhs.length) {
699             this.setEquals(false);
700             return this;
701         }
702         for (int i = 0; i < lhs.length && isEquals; ++i) {
703             append(lhs[i], rhs[i]);
704         }
705         return this;
706     }
707
708     /**
709      * <p>Deep comparison of array of <code>boolean</code>. Length and all
710      * values are compared.</p>
711      *
712      * <p>The method {@link #append(boolean, boolean)} is used.</p>
713      *
714      * @param lhs the left hand <code>boolean[]</code>
715      * @param rhs the right hand <code>boolean[]</code>
716      * @return EqualsBuilder - used to chain calls.
717      */

718     public EqualsBuilder append(boolean[] lhs, boolean[] rhs) {
719         if (isEquals == false) {
720             return this;
721         }
722         if (lhs == rhs) {
723             return this;
724         }
725         if (lhs == null || rhs == null) {
726             this.setEquals(false);
727             return this;
728         }
729         if (lhs.length != rhs.length) {
730             this.setEquals(false);
731             return this;
732         }
733         for (int i = 0; i < lhs.length && isEquals; ++i) {
734             append(lhs[i], rhs[i]);
735         }
736         return this;
737     }
738
739     /**
740      * <p>Returns <code>true</code> if the fields that have been checked
741      * are all equal.</p>
742      *
743      * @return boolean
744      */

745     public boolean isEquals() {
746         return this.isEquals;
747     }
748
749     /**
750      * Sets the <code>isEquals</code> value.
751      *
752      * @param isEquals The value to set.
753      * @since 2.1
754      */

755     protected void setEquals(boolean isEquals) {
756         this.isEquals = isEquals;
757     }
758 }
759
Popular Tags