forked from jqno/equalsverifier
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
jqno#540 BigDecimal equality using compareTo
- Loading branch information
Showing
6 changed files
with
449 additions
and
170 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
--- | ||
title: "`BigDecimal` equality using `compareTo(BigDecimal val)`" | ||
permalink: /manual/bigdecimal-equality/ | ||
--- | ||
The `Comparable` interface strongly recommends but does not require that implementations consider two objects equal using `compareTo` whenever they are equal using `equals` and vice versa. `BigDecimal` is a class where this is not applied. | ||
|
||
{% highlight java %} | ||
BigDecimal zero = new BigDecimal("0"); | ||
BigDecimal alsoZero = new BigDecimal("0.0"); | ||
|
||
// prints true - zero is the same as zero | ||
System.out.println(zero.compareTo(alsoZero) == 0); | ||
// prints false - zero is not the same as zero | ||
System.out.println(zero.equals(alsoZero)); | ||
{% endhighlight %} | ||
|
||
This is because `BigDecimal` can have multiple representations of the same value. It uses an unscaled value and a scale so, for example, the value of 1 can be represented as unscaled value 1 with scale of 0 (the number of places after the decimal point) or as unscaled value 10 with scale of 1 resolving to 1.0. Its `equals` and `hashCode` methods use both of these attributes in their calculation rather than the resolved value. | ||
|
||
If your class contains any `BigDecimal` fields, in order for comparably equal values to be considered the same, then the `equals` method must use `compareTo` for the check and the `hashCode` calculation must derive the same value for all `BigDecimal` instances that are equal using `compareTo` (taking care if it is a nullable field). | ||
|
||
EqualsVerifier will check this by default. If you do not have this requirement the check can be disabled by suppressing `Warning.BIGDECIMAL_EQUALITY`. | ||
|
||
{% highlight java %} | ||
EqualsVerifier.forClass(FooWithComparablyEqualBigDecimalFields.class) | ||
.suppress(Warning.BIGDECIMAL_EQUALITY) | ||
.verify(); | ||
{% endhighlight %} | ||
|
||
There is more information on `compareTo` and `equals` in the `Comparable` Javadoc and Effective Java's chapter on implementing `Comparable`. | ||
There is more information on `BigDecimal` in its Javadoc (and its representation can be seen by printing `unscaledValue()` and `scale()`). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,170 +1,185 @@ | ||
package nl.jqno.equalsverifier; | ||
|
||
/** | ||
* Enum of warnings that can be suppressed in {@link nl.jqno.equalsverifier.EqualsVerifier}. | ||
* | ||
* @see nl.jqno.equalsverifier.api.EqualsVerifierApi#suppress(Warning...) | ||
*/ | ||
public enum Warning { | ||
/** | ||
* Signals that not all fields are relevant in the {@code equals} contract. {@code | ||
* EqualsVerifier} will not fail if one or more fields do not affect the outcome of {@code | ||
* equals}. | ||
* | ||
* <p>Only applies to non-transient fields. | ||
*/ | ||
ALL_FIELDS_SHOULD_BE_USED, | ||
|
||
/** | ||
* Signals that non-final fields are not relevant in the {@code equals} contract. {@code | ||
* EqualsVerifier} will not fail if one or more non-final fields do not affect the outcome of | ||
* {@code equals}. | ||
* | ||
* <p>Only applies to non-transient fields. | ||
*/ | ||
ALL_NONFINAL_FIELDS_SHOULD_BE_USED, | ||
|
||
/** | ||
* Disables the check for reference equality on fields. | ||
* | ||
* <p>EqualsVerifier will check if the {@code equals} method calls equals on the object fields | ||
* of the class under test, instead of the {@code ==} operator, since normally this signifies a | ||
* mistake (e.g. comparing string fields with {@code ==}). | ||
* | ||
* <p>However, sometimes {@code ==} is used intentionally, or the field in question doesn't | ||
* implement {@code equals} itself, so a call to the {@code equals} method of that field is | ||
* essentially a reference equality check instead of a value equality check. In these cases, | ||
* this warning can be suppressed. | ||
*/ | ||
REFERENCE_EQUALITY, | ||
|
||
/** | ||
* Disables the check, when the {@code equals} method is overridden in the class under test, | ||
* that an instance of this class should be equal to an identical copy of itself. | ||
* | ||
* <p>Normally, it is important that an object be equal to an identical copy of itself: after | ||
* all, this is the point of overriding {@code equals} in the first place. | ||
* | ||
* <p>However, when the class is part of a hierarchy, but should be (pseudo-)singleton, it can | ||
* be useful to suppress this warning. This can happen in certain implementations of the Null | ||
* Object Pattern, for example. | ||
* | ||
* <p>If this warning is suppressed, and it turns out that an instance of the class under test | ||
* is equal to an identical copy of itself after all, {@link EqualsVerifier} will fail. | ||
*/ | ||
IDENTICAL_COPY, | ||
|
||
/** | ||
* Disables the check, when the {@code equals} method is overridden in the class under test, | ||
* that an instance of this class should be equal to an identical copy of itself. | ||
* | ||
* <p>Normally, it is important that an object be equal to an identical copy of itself: after | ||
* all, this is the point of overriding {@code equals} in the first place. | ||
* | ||
* <p>However, when the class is a kind of versioned entity and there is an {@code id} field | ||
* that is zero when the object is new, it is often the case that two new objects are never | ||
* equal to each other. In these cases, it can be useful to suppress this warning. | ||
* | ||
* <p>You cannot use {@link #IDENTICAL_COPY} in these cases, because when the {@code id}s are | ||
* equal, the objects should be, too, and {@link EqualsVerifier} would fail in this case. | ||
* | ||
* <p>If this warning is suppressed, and it turns out that an instance of the class under test | ||
* is equal to an identical copy of itself after all, {@link EqualsVerifier} will NOT fail. | ||
*/ | ||
IDENTICAL_COPY_FOR_VERSIONED_ENTITY, | ||
|
||
/** | ||
* Disables the check that verifies {@code equals} is actually overridden. | ||
* | ||
* <p>Can be used when a whole package of classes is automatically scanned and presented to | ||
* EqualsVerifier, and one or more of them don't need to override {@code equals}. | ||
*/ | ||
INHERITED_DIRECTLY_FROM_OBJECT, | ||
|
||
/** | ||
* Disables the example check for cached {@code hashCode}. | ||
* | ||
* <p>The example check verifies that the cached {@code hashCode} is properly initialized. You | ||
* can use this, if creating an example object is too cumbersome. In this case, null can be | ||
* passed as an example. | ||
* | ||
* <p>Note that suppressing this warning can be dangerous and should only be done in unusual | ||
* circumstances. | ||
*/ | ||
NO_EXAMPLE_FOR_CACHED_HASHCODE, | ||
|
||
/** | ||
* Disables checks for non-final fields on which {@code equals} and {@code hashCode} depend. | ||
* | ||
* <p>{@link EqualsVerifier}'s standard behaviour is to disallow non-final fields being used in | ||
* {@code equals} and {@code hashCode} methods, since classes that depend on non-final fields in | ||
* these methods cannot reliably be used in collections. | ||
* | ||
* <p>However, sometimes an external library requires that fields be non-final. An example of | ||
* this are Java Beans. In such a case, suppress this warning to prevent {@link EqualsVerifier} | ||
* from checking for non-final fields. | ||
*/ | ||
NONFINAL_FIELDS, | ||
|
||
/** | ||
* Disables checks for {@link NullPointerException} within {@code equals}, {@code hashCode} and | ||
* {@code toString} methods. | ||
* | ||
* <p>Sometimes the constructor of a class makes sure no field can be null. If this is the case, | ||
* and if the fields cannot be made null later in the lifecycle of the class by setters or other | ||
* methods, suppress this warning to disable the check for {@link NullPointerException}. | ||
*/ | ||
NULL_FIELDS, | ||
|
||
/** | ||
* Disables the check that all fields used in {@code equals} must also be used in {@code | ||
* hashCode}. | ||
* | ||
* <p>This is useful when bringing legacy systems under test, where you don't want to change the | ||
* existing {@code hashCode} behaviour but you do want to use EqualsVerifier. | ||
* | ||
* <p>Note that {@code hashCode}s with higher distributions give better performance when used in | ||
* collections such as {@link java.util.HashMap}. Therefore, if possible, you should use all | ||
* fields that are used in {@code equals}, in {@code hashCode} as well. | ||
*/ | ||
STRICT_HASHCODE, | ||
|
||
/** | ||
* Disables some of the stricter inheritance tests. | ||
* | ||
* <p>{@link EqualsVerifier}'s standard behaviour, if T is not final and neither are its {@code | ||
* equals} and {@code hashCode} methods, is to require a reference to a subclass of T for which | ||
* no instance can be equal to any instance of T, to make sure that subclasses that can redefine | ||
* {@code equals} or {@code hashCode} don't break the contract; or it asks to call the {@code | ||
* usingGetClass} method if T uses {@code getClass()} instead of {@code instanceof} in its | ||
* {@code equals} method. | ||
* | ||
* <p>Some may find that too strict for their liking; suppressing this warning disables that | ||
* test. | ||
* | ||
* @see nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi#withRedefinedSubclass(Class) | ||
*/ | ||
STRICT_INHERITANCE, | ||
|
||
/** | ||
* Disables the check that fields marked with the @Id or @EmbeddedId annotations in JPA entities | ||
* may not be used in the {@code equals} contract. | ||
* | ||
* <p>When this warning is suppressed, the fields marked with @Id or @EmbeddedId will become the | ||
* entity's surrogate key. Only these fields can now be part of the {@code equals} contract; all | ||
* other fields may no longer be used in {@code equals}. | ||
*/ | ||
SURROGATE_KEY, | ||
|
||
/** | ||
* Disables the check that transient fields not be part of the {@code equals} contract. | ||
* | ||
* <p>{@link EqualsVerifier}'s standard behaviour is to disallow transient fields being used in | ||
* {@code equals} and {@code hashCode} methods, since these fields may not be restored to their | ||
* original state after deserialization, which would break {@code equals}. | ||
* | ||
* <p>If measures are taken that this will never happen, this warning can be suppressed to | ||
* disable {@link EqualsVerifier}'s transience test. | ||
*/ | ||
TRANSIENT_FIELDS | ||
} | ||
package nl.jqno.equalsverifier; | ||
|
||
/** | ||
* Enum of warnings that can be suppressed in {@link nl.jqno.equalsverifier.EqualsVerifier}. | ||
* | ||
* @see nl.jqno.equalsverifier.api.EqualsVerifierApi#suppress(Warning...) | ||
*/ | ||
public enum Warning { | ||
/** | ||
* Signals that not all fields are relevant in the {@code equals} contract. {@code | ||
* EqualsVerifier} will not fail if one or more fields do not affect the outcome of {@code | ||
* equals}. | ||
* | ||
* <p>Only applies to non-transient fields. | ||
*/ | ||
ALL_FIELDS_SHOULD_BE_USED, | ||
|
||
/** | ||
* Signals that non-final fields are not relevant in the {@code equals} contract. {@code | ||
* EqualsVerifier} will not fail if one or more non-final fields do not affect the outcome of | ||
* {@code equals}. | ||
* | ||
* <p>Only applies to non-transient fields. | ||
*/ | ||
ALL_NONFINAL_FIELDS_SHOULD_BE_USED, | ||
|
||
/** | ||
* Disables the check for reference equality on fields. | ||
* | ||
* <p>EqualsVerifier will check if the {@code equals} method calls equals on the object fields | ||
* of the class under test, instead of the {@code ==} operator, since normally this signifies a | ||
* mistake (e.g. comparing string fields with {@code ==}). | ||
* | ||
* <p>However, sometimes {@code ==} is used intentionally, or the field in question doesn't | ||
* implement {@code equals} itself, so a call to the {@code equals} method of that field is | ||
* essentially a reference equality check instead of a value equality check. In these cases, | ||
* this warning can be suppressed. | ||
*/ | ||
REFERENCE_EQUALITY, | ||
|
||
/** | ||
* Disables the check, when the {@code equals} method is overridden in the class under test, | ||
* that an instance of this class should be equal to an identical copy of itself. | ||
* | ||
* <p>Normally, it is important that an object be equal to an identical copy of itself: after | ||
* all, this is the point of overriding {@code equals} in the first place. | ||
* | ||
* <p>However, when the class is part of a hierarchy, but should be (pseudo-)singleton, it can | ||
* be useful to suppress this warning. This can happen in certain implementations of the Null | ||
* Object Pattern, for example. | ||
* | ||
* <p>If this warning is suppressed, and it turns out that an instance of the class under test | ||
* is equal to an identical copy of itself after all, {@link EqualsVerifier} will fail. | ||
*/ | ||
IDENTICAL_COPY, | ||
|
||
/** | ||
* Disables the check, when the {@code equals} method is overridden in the class under test, | ||
* that an instance of this class should be equal to an identical copy of itself. | ||
* | ||
* <p>Normally, it is important that an object be equal to an identical copy of itself: after | ||
* all, this is the point of overriding {@code equals} in the first place. | ||
* | ||
* <p>However, when the class is a kind of versioned entity and there is an {@code id} field | ||
* that is zero when the object is new, it is often the case that two new objects are never | ||
* equal to each other. In these cases, it can be useful to suppress this warning. | ||
* | ||
* <p>You cannot use {@link #IDENTICAL_COPY} in these cases, because when the {@code id}s are | ||
* equal, the objects should be, too, and {@link EqualsVerifier} would fail in this case. | ||
* | ||
* <p>If this warning is suppressed, and it turns out that an instance of the class under test | ||
* is equal to an identical copy of itself after all, {@link EqualsVerifier} will NOT fail. | ||
*/ | ||
IDENTICAL_COPY_FOR_VERSIONED_ENTITY, | ||
|
||
/** | ||
* Disables the check that verifies {@code equals} is actually overridden. | ||
* | ||
* <p>Can be used when a whole package of classes is automatically scanned and presented to | ||
* EqualsVerifier, and one or more of them don't need to override {@code equals}. | ||
*/ | ||
INHERITED_DIRECTLY_FROM_OBJECT, | ||
|
||
/** | ||
* Disables the example check for cached {@code hashCode}. | ||
* | ||
* <p>The example check verifies that the cached {@code hashCode} is properly initialized. You | ||
* can use this, if creating an example object is too cumbersome. In this case, null can be | ||
* passed as an example. | ||
* | ||
* <p>Note that suppressing this warning can be dangerous and should only be done in unusual | ||
* circumstances. | ||
*/ | ||
NO_EXAMPLE_FOR_CACHED_HASHCODE, | ||
|
||
/** | ||
* Disables checks for non-final fields on which {@code equals} and {@code hashCode} depend. | ||
* | ||
* <p>{@link EqualsVerifier}'s standard behaviour is to disallow non-final fields being used in | ||
* {@code equals} and {@code hashCode} methods, since classes that depend on non-final fields in | ||
* these methods cannot reliably be used in collections. | ||
* | ||
* <p>However, sometimes an external library requires that fields be non-final. An example of | ||
* this are Java Beans. In such a case, suppress this warning to prevent {@link EqualsVerifier} | ||
* from checking for non-final fields. | ||
*/ | ||
NONFINAL_FIELDS, | ||
|
||
/** | ||
* Disables checks for {@link NullPointerException} within {@code equals}, {@code hashCode} and | ||
* {@code toString} methods. | ||
* | ||
* <p>Sometimes the constructor of a class makes sure no field can be null. If this is the case, | ||
* and if the fields cannot be made null later in the lifecycle of the class by setters or other | ||
* methods, suppress this warning to disable the check for {@link NullPointerException}. | ||
*/ | ||
NULL_FIELDS, | ||
|
||
/** | ||
* Disables the check that all fields used in {@code equals} must also be used in {@code | ||
* hashCode}. | ||
* | ||
* <p>This is useful when bringing legacy systems under test, where you don't want to change the | ||
* existing {@code hashCode} behaviour but you do want to use EqualsVerifier. | ||
* | ||
* <p>Note that {@code hashCode}s with higher distributions give better performance when used in | ||
* collections such as {@link java.util.HashMap}. Therefore, if possible, you should use all | ||
* fields that are used in {@code equals}, in {@code hashCode} as well. | ||
*/ | ||
STRICT_HASHCODE, | ||
|
||
/** | ||
* Disables some of the stricter inheritance tests. | ||
* | ||
* <p>{@link EqualsVerifier}'s standard behaviour, if T is not final and neither are its {@code | ||
* equals} and {@code hashCode} methods, is to require a reference to a subclass of T for which | ||
* no instance can be equal to any instance of T, to make sure that subclasses that can redefine | ||
* {@code equals} or {@code hashCode} don't break the contract; or it asks to call the {@code | ||
* usingGetClass} method if T uses {@code getClass()} instead of {@code instanceof} in its | ||
* {@code equals} method. | ||
* | ||
* <p>Some may find that too strict for their liking; suppressing this warning disables that | ||
* test. | ||
* | ||
* @see nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi#withRedefinedSubclass(Class) | ||
*/ | ||
STRICT_INHERITANCE, | ||
|
||
/** | ||
* Disables the check that fields marked with the @Id or @EmbeddedId annotations in JPA entities | ||
* may not be used in the {@code equals} contract. | ||
* | ||
* <p>When this warning is suppressed, the fields marked with @Id or @EmbeddedId will become the | ||
* entity's surrogate key. Only these fields can now be part of the {@code equals} contract; all | ||
* other fields may no longer be used in {@code equals}. | ||
*/ | ||
SURROGATE_KEY, | ||
|
||
/** | ||
* Disables the check that transient fields not be part of the {@code equals} contract. | ||
* | ||
* <p>{@link EqualsVerifier}'s standard behaviour is to disallow transient fields being used in | ||
* {@code equals} and {@code hashCode} methods, since these fields may not be restored to their | ||
* original state after deserialization, which would break {@code equals}. | ||
* | ||
* <p>If measures are taken that this will never happen, this warning can be suppressed to | ||
* disable {@link EqualsVerifier}'s transience test. | ||
*/ | ||
TRANSIENT_FIELDS, | ||
|
||
/** | ||
* Disables the check that equality of {@code BigDecimal} fields is implemented using | ||
* {@code compareTo} rather than {@code equals}. | ||
* | ||
* <p>{@code BigDecimal} objects that are equal using {@code compareTo} are not necessarily | ||
* equal using {@code equals}, for example the values of {@literal 1} and {@literal 1.0}. | ||
* For variants of the same value to be considered equal, classes with {@code BigDecimal} | ||
* fields should use {@code compareTo} to check equality of non-null {@code BigDecimal} | ||
* references and produce the same hashcode for all equal variants. | ||
* | ||
* <p>{@code EqualsVerifier} checks for this by default but it can be disabled by suppressing | ||
* this warning. | ||
*/ | ||
BIGDECIMAL_EQUALITY | ||
} |
Oops, something went wrong.