# copying Companion code for the ankurm.com post *"Deep Copy vs Shallow Copy in Java: clone(), Copy Constructors, Serialization and Records."* Module in `java-core-examples`, the Java-core series. There is no `docs/` folder: the deeper material lives in the post itself, inside its expandable sections. ## Versions this was built and tested against | Component | Version | Notes | |---|---|---| | JDK | 25.0.5+8 (Temurin, LTS) | Records, `List.copyOf`, `Arrays.copyOf`. | | JUnit Jupiter | 5.11.0 | Same as the sibling modules. | | Maven | 3.9.11 | | ## Quickstart ```bash export JAVA_HOME=/path/to/jdk-25 mvn compile scripts/run.sh CloneDemo # one demo scripts/broken.sh # the three deliberate compile errors scripts/run-all.sh # regenerate every file in output/ ``` ## What's in here | File | What it shows | |---|---| | `ShallowVsDeepDemo.java` | Assignment vs shallow copy vs deep copy on one `Person` graph. | | `CloneDemo.java` | `clone()` skips the constructor, is shallow, needs `Cloneable`, and a parent that uses `new` breaks subclasses. Arrays and `ArrayList.clone()` are shallow too. | | `src/broken/FinalFieldClone.java` | Does not compile: a `final` field cannot be deep-copied inside `clone()`. Not part of the Maven build. | | `src/broken/ForgotToOverride.java` | Does not compile: `implements Cloneable` without a public `clone()` override leaves `clone()` protected. | | `src/broken/WithExpression.java` | Does not compile on JDK 25: the `with` expression of JEP 468 (derived record creation) is not part of the language yet. | | `CopyConstructorDemo.java` | Copy constructors with `final` fields, subtype slicing, and a virtual `copy()` that fixes it. | | `SerializationCopyDemo.java` | Deep copy via `ObjectOutputStream`: `transient` loss, shared references and cycles preserved, `NotSerializableException`. | | `RecordCopyDemo.java` | Records are only shallowly immutable: `List.copyOf` in the compact constructor, withers, a mutable `Date` component. | | `DefensiveCopyDemo.java` | Leaks through constructor and getter; `unmodifiableList` (view) vs `List.copyOf` (snapshot). | | `CollectionCopyDemo.java` | Every standard list, map and array copy is shallow; the deep versions. | | `CopyOfIdentityDemo.java` | When `List.copyOf` returns the same instance and when it copies; null elements. | | `GraphCopyDemo.java` | Shared nodes and cycles: a recursive copy constructor duplicates the shared node and overflows the stack on a cycle; an identity-map copy and serialization both handle them. | | `SerializationRulesDemo.java` | Which constructors run during a serialization copy (classes vs records) and an `ObjectInputFilter` allow-list. | | `RecordArrayDemo.java` | An array record component leaks through the constructor and the accessor; the generated `equals()` compares arrays by identity. | | `DefensiveCloneDemo.java` | Why a defensive copy must not call `clone()` on a non-final parameter type (a `Date` subclass hands back itself). | | `CopyCostDemo.java` | Indicative cost of copy constructor vs `clone()` vs serialization. Timing: results drift per run. | | `CopyingTest.java`, `CopyingExtrasTest.java` | Pin every claim above as an assertion (17 + 7 = 24 tests). | | `output/01-17` | Captured runs of everything above. `10-cost.txt` is the only non-deterministic file. | ## License MIT - see [LICENSE](../LICENSE).