2

Is there a generic utility in Java to check equality of a shallow copy? In the given example how do verify the shallow copy without of course rolling out my own implementation of equals()

public class ClonableExample {
    public static class ClonableObject implements Cloneable, Serializable {
        @Override public ClonableObject clone() throws CloneNotSupportedException {return (ClonableObject) super.clone();}
    }

    public static void main(String[] args) throws CloneNotSupportedException {
        ClonableObject b = new ClonableObject();

        System.out.println(b != b.clone());
        System.out.println(b.equals(b.clone())); // Reference check fails
        System.out.println(Objects.equals(b, b.clone())); // Nothing fancy but still a reference check that fails
        System.out.println(Objects.deepEquals(b, b.clone())); // Reference check + Arrays.equals checks both of which fail
    }
}

Open to 3rd party libraries if not available in core java

hamlet
  • 127
  • 8
  • You could use Kotlin data classes or Lombok annotations. https://stackoverflow.com/q/50449603/14955 – Thilo Mar 01 '20 at 09:17
  • 3
    Or maybe use the reflection-based Commons Lang EqualsBuilder: https://stackoverflow.com/a/13496182/14955 https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/builder/EqualsBuilder.html#reflectionEquals-java.lang.Object-java.lang.Object-boolean- – Thilo Mar 01 '20 at 09:19
  • You can use `EqualsBuilder (Apache Commons Lang 3.9 API)` -> `EqualsBuilder.reflectionEquals(b, b.clone(), true) >> true` – kozmo Mar 01 '20 at 09:19
  • 2
    However, resorting to means like that is a bit of a design smell. – Thilo Mar 01 '20 at 09:21
  • Thanks @Thilo, works for me for now. Why would you say that it is a design smell though? – hamlet Mar 01 '20 at 09:38
  • Reflection should be a last measure if nothing else works. https://softwareengineering.stackexchange.com/questions/193526/is-it-a-bad-habit-to-overuse-reflection For the example at hand, the Java designers gave every object an `equals` method for a reason. You are supposed to implement it in the way that makes sense for the particular class. – Thilo Mar 01 '20 at 09:48
  • Got it. Thanks @Thilo for your comments. All aggregated would have been a great answer – hamlet Mar 01 '20 at 09:56

1 Answers1

0

EqualsBuilder (Apache Commons Lang API) -> Gradle: group: 'org.apache.commons', name: 'commons-lang3', version: '3.9'

public static class CloneableObject implements Cloneable, Serializable {
    @Override 
    public CloneableObject clone() throws CloneNotSupportedException {
        return (CloneableObject) super.clone();
    }
}

System.out.println(EqualsBuilder.reflectionEquals(b, b.clone(), true)); // true
kozmo
  • 4,024
  • 3
  • 30
  • 48
  • Thanks @kozmo. Anything for comparing deep copies along the same lines? I see SerializationUtils.clone() probably allows for a deep copy as well – hamlet Mar 01 '20 at 09:46
  • For deep comparison, use the `testRecursive` option on `reflectionEquals`. – Thilo Mar 01 '20 at 09:51