From e12b796996e3cd69694f0098bee9b162e280f5b7 Mon Sep 17 00:00:00 2001 From: Deepak Vohra Date: Thu, 23 Oct 2025 15:53:23 -0700 Subject: [PATCH 1/9] Implement Car class with Object method overrides The Car class implements Cloneable and overrides Object methods for equality, hashing, string representation, and cloning. --- .../com/baeldung/object-class-guide/Car.java | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/object-class-guide/Car.java diff --git a/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/object-class-guide/Car.java b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/object-class-guide/Car.java new file mode 100644 index 000000000000..2345247b9c9a --- /dev/null +++ b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/object-class-guide/Car.java @@ -0,0 +1,76 @@ +import java.util.Objects; + + +/** + * Represents a car object, implementing Cloneable and overriding Object methods. + * + * The class uses standard implementation for equals(), hashCode(), and toString(). + * The clone() method performs a shallow copy, which is sufficient since 'make' (String) + * and 'year' (int) are immutable or primitive. + */ +public class Car implements Cloneable { + private String make; + private int year; + + + public Car(String make, int year) { + this.make = make; + this.year = year; + } + + + // Getters for external access (useful for testing) + public String getMake() { + return make; + } + + + public int getYear() { + return year; + } + + + /** + * Standard implementation of equals() for value equality. + */ + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + Car car = (Car) obj; + // Use Objects.equals for safe String comparison + return year == car.year && Objects.equals(make, car.make); + } + + + /** + * Standard implementation of hashCode() based on make and year. + */ + @Override + public int hashCode() { + return Objects.hash(make, year); + } + + + /** + * Standard implementation of toString() for debugging and logging. + */ + @Override + public String toString() { + return "Car{" + + "make='" + make + '\'' + + ", year=" + year + + '}'; + } + + + /** + * Overrides the protected clone() method from Object to perform a shallow copy. + * This is the standard pattern when implementing the Cloneable marker interface. + */ + @Override + public Object clone() throws CloneNotSupportedException { + // Calls Object's native clone() method + return super.clone(); + } +} From 92cc12807110d1282354480b7805bc7c258a9150 Mon Sep 17 00:00:00 2001 From: Deepak Vohra Date: Thu, 23 Oct 2025 16:04:45 -0700 Subject: [PATCH 2/9] Rename Car.java to follow package naming convention --- .../baeldung/{object-class-guide => objectclassguide}/Car.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/{object-class-guide => objectclassguide}/Car.java (100%) diff --git a/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/object-class-guide/Car.java b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/objectclassguide/Car.java similarity index 100% rename from core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/object-class-guide/Car.java rename to core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/objectclassguide/Car.java From 49fd8718507c7539b08c4d1e452561d42d89c5a0 Mon Sep 17 00:00:00 2001 From: Deepak Vohra Date: Thu, 23 Oct 2025 16:07:04 -0700 Subject: [PATCH 3/9] Add package declaration to CarObjectUnitTests --- .../objectclassguide/CarObjectUnitTests.java | 261 ++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/objectclassguide/CarObjectUnitTests.java diff --git a/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/objectclassguide/CarObjectUnitTests.java b/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/objectclassguide/CarObjectUnitTests.java new file mode 100644 index 000000000000..04fe54fdb73b --- /dev/null +++ b/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/objectclassguide/CarObjectUnitTests.java @@ -0,0 +1,261 @@ +package com.baeldung.objectclassguide; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.DisplayName; +import static org.junit.jupiter.api.Assertions.*; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Merged JUnit 5 tests for the Car class, focusing on standard + * Object methods (equals, hashCode, toString, getClass) and + * advanced methods (clone, wait/notify, finalize). + * + * NOTE: It is assumed that a 'Car' class exists with 'make' (String) + * and 'year' (int) fields, and correctly implements or overrides + * the Object methods being tested (including a 'getMake' and 'getYear' + * for the clone test, and optionally implements Cloneable). + */ +public class CarObjectUnitTests { + + private final String TEST_MAKE = "Honda"; + private final int TEST_YEAR = 2020; + + // --- equals() Tests (from first test block) --- + + @Test + void testEquals_Reflexive() { + Car car1 = new Car("Honda", 2020); + // An object must equal itself. + assertTrue(car1.equals(car1), "Must be reflexive"); + } + + @Test + void testEquals_Symmetric() { + Car car1 = new Car("Honda", 2020); + Car car2 = new Car("Honda", 2020); + // If car1.equals(car2) is true, then car2.equals(car1) must be true. + assertTrue(car1.equals(car2), "Symmetry part 1"); + assertTrue(car2.equals(car1), "Symmetry part 2"); + } + + @Test + void testEquals_Transitive() { + Car car1 = new Car("Honda", 2020); + Car car2 = new Car("Honda", 2020); + Car car3 = new Car("Honda", 2020); + + // If a==b and b==c, then a must equal c. + assertTrue(car1.equals(car2)); + assertTrue(car2.equals(car3)); + assertTrue(car1.equals(car3), "Must be transitive"); + } + + @Test + void testEquals_NotEqual() { + Car car1 = new Car("Honda", 2020); + Car car2 = new Car("Toyota", 2020); // Different make + + assertFalse(car1.equals(car2), "Objects with different state should be unequal"); + } + + @Test + void testEquals_Null() { + Car car1 = new Car("Honda", 2020); + // Must return false when compared to null. + assertFalse(car1.equals(null), "Must return false for null"); + } + + // --- hashCode() Tests (from second test block) --- + + @Test + void testHashCode_EqualObjects() { + Car car1 = new Car("Honda", 2020); + Car car2 = new Car("Honda", 2020); + + // Equal objects MUST have equal hash codes. + assertEquals(car1.hashCode(), car2.hashCode(), + "Equal objects must have identical hash codes"); + } + + @Test + void testHashCode_Consistent() { + Car car = new Car("Honda", 2020); + int initialHash = car.hashCode(); + + // If the object's fields haven't changed, hashCode() must return the same value. + assertEquals(initialHash, car.hashCode(), + "hashCode() must be consistent across multiple calls"); + } + + // --- toString() Test (from third test block) --- + + @Test + void testToString() { + Car car = new Car("Tesla", 2023); + String expected = "Car{make='Tesla', year=2023}"; + + // Check if the output matches the expected formatted string. + assertEquals(expected, car.toString(), + "toString() should return a human-readable representation of the object's state"); + } + + // --- getClass() Test (from fourth test block) --- + + @Test + void testGetClass() { + Car car = new Car("Ford", 2015); + + // The returned Class object must match the Car class. + assertEquals(Car.class, car.getClass(), + "getClass() must return the runtime Class object"); + } + + // --- clone() Test (from fifth test block) --- + + @Test + @DisplayName("Test shallow cloning maintains value equality") + void testClone_Success() throws CloneNotSupportedException { + // Assuming Car class implements Cloneable and overrides clone() + Car original = new Car(TEST_MAKE, TEST_YEAR); + Car cloned = (Car) original.clone(); + + // 1. Should be different objects (reference inequality) + assertNotSame(original, cloned, "The cloned object should be a new instance."); + + // 2. Should have the same values (value equality) + assertEquals(original, cloned, "Cloned object should be equal to the original."); + // Note: The original test block implied the existence of getMake/getYear. + // These are used to verify shallow copy correctness. + // assertEquals(original.getMake(), cloned.getMake(), "Make field should be identical."); + // assertEquals(original.getYear(), cloned.getYear(), "Year field should be identical."); + } + + // --- wait(), notify(), notifyAll() Tests (Synchronization - from fifth test block) --- + + @Test + @DisplayName("Test wait() throws IllegalMonitorStateException when not synchronized") + void testWait_IllegalMonitorState() { + Car car = new Car(TEST_MAKE, TEST_YEAR); + + // Assert that calling wait() without a monitor (synchronized block) throws the expected exception + assertThrows(IllegalMonitorStateException.class, () -> { + car.wait(); + }, "wait() must throw IllegalMonitorStateException when called outside a synchronized block."); + } + + @Test + @DisplayName("Test notify() throws IllegalMonitorStateException when not synchronized") + void testNotify_IllegalMonitorState() { + Car car = new Car(TEST_MAKE, TEST_YEAR); + + // Assert that calling notify() without a monitor (synchronized block) throws the expected exception + assertThrows(IllegalMonitorStateException.class, () -> { + car.notify(); + }, "notify() must throw IllegalMonitorStateException when called outside a synchronized block."); + } + + @Test + @DisplayName("Test notifyAll() throws IllegalMonitorStateException when not synchronized") + void testNotifyAll_IllegalMonitorState() { + Car car = new Car(TEST_MAKE, TEST_YEAR); + + // Assert that calling notifyAll() without a monitor (synchronized block) throws the expected exception + assertThrows(IllegalMonitorStateException.class, () -> { + car.notifyAll(); + }, "notifyAll() must throw IllegalMonitorStateException when called outside a synchronized block."); + } + + @Test + @DisplayName("Test timed wait() inside synchronized block does not throw exception") + void testWait_SynchronizedSuccess() { + Car car = new Car(TEST_MAKE, TEST_YEAR); + + assertDoesNotThrow(() -> { + synchronized (car) { + // Wait for a very short time (1ms) to verify the call is legal + car.wait(1); + } + }, "wait() call inside synchronized block should not throw an exception."); + } + + // --- finalize() Test (Conceptual - from fifth test block) --- + + private static AtomicBoolean finalizedFlag = new AtomicBoolean(false); + + // A nested class that overrides finalize() for demonstration purposes + private static class FinalizableCar extends Car { + public FinalizableCar(String make, int year) { + // Assuming Car has a constructor Car(String, int) + super(make, year); + } + + @Override + protected void finalize() throws Throwable { + try { + finalizedFlag.set(true); + } finally { + super.finalize(); + } + } + } + + @Test + @DisplayName("Conceptual Test for finalize() (Execution is non-deterministic)") + void testFinalize_Conceptual() { + // Reset the flag + finalizedFlag.set(false); + + // Create an object and make it unreachable + new FinalizableCar(TEST_MAKE, TEST_YEAR); + + // Suggest Garbage Collection (Non-deterministic and unreliable for testing) + System.gc(); + + // The assertion for finalizedFlag is commented out as it's non-deterministic. + System.out.println("\n*** finalize() Test Note ***"); + System.out.println("The finalize() method is deprecated and its execution is non-deterministic."); + System.out.println("Current status of finalization flag after System.gc() (Unreliable): " + finalizedFlag.get()); + System.out.println("****************************\n"); + } +} + +// NOTE: The Car class definition is assumed to exist in the environment +// but is not provided here, as the request was only to merge the tests. + +// Example placeholder for the Car class (must be available for the tests to compile): +class Car implements Cloneable { + private final String make; + private final int year; + + public Car(String make, int year) { + this.make = make; + this.year = year; + } + + public String getMake() { return make; } + public int getYear() { return year; } + + // Implementations for the tested methods would go here... + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Car car = (Car) o; + return year == car.year && make.equals(car.make); + } + + @Override + public int hashCode() { + return java.util.Objects.hash(make, year); + } + + @Override + public String toString() { + return "Car{make='" + make + "', year=" + year + "}"; + } + + @Override + protected Object clone() throws CloneNotSupportedException { + return super.clone(); + } +} From f50e32ebba704121a20839998055f3f70ee38339 Mon Sep 17 00:00:00 2001 From: Deepak Vohra Date: Thu, 23 Oct 2025 16:07:46 -0700 Subject: [PATCH 4/9] Add package declaration to Car.java --- .../src/main/java/com/baeldung/objectclassguide/Car.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/objectclassguide/Car.java b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/objectclassguide/Car.java index 2345247b9c9a..8f88be033632 100644 --- a/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/objectclassguide/Car.java +++ b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/objectclassguide/Car.java @@ -1,3 +1,5 @@ +package com.baeldung.objectclassguide; + import java.util.Objects; From 307cb723cbf54cc9a01e01a3fceecd1150d71961 Mon Sep 17 00:00:00 2001 From: Deepak Vohra Date: Thu, 23 Oct 2025 17:36:27 -0700 Subject: [PATCH 5/9] Rename test methods for better readability --- .../objectclassguide/CarObjectUnitTests.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/objectclassguide/CarObjectUnitTests.java b/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/objectclassguide/CarObjectUnitTests.java index 04fe54fdb73b..6c9774d871c1 100644 --- a/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/objectclassguide/CarObjectUnitTests.java +++ b/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/objectclassguide/CarObjectUnitTests.java @@ -23,14 +23,14 @@ public class CarObjectUnitTests { // --- equals() Tests (from first test block) --- @Test - void testEquals_Reflexive() { + void givenACarObject_whenTestingObjectEqualsItself_thenEqualsReflexive() { Car car1 = new Car("Honda", 2020); // An object must equal itself. assertTrue(car1.equals(car1), "Must be reflexive"); } @Test - void testEquals_Symmetric() { + void givenTwoCarObjects_whenTestingSymmetric_thenEqualsSymmetric() { Car car1 = new Car("Honda", 2020); Car car2 = new Car("Honda", 2020); // If car1.equals(car2) is true, then car2.equals(car1) must be true. @@ -39,7 +39,7 @@ void testEquals_Symmetric() { } @Test - void testEquals_Transitive() { + void givenThreeCarObjects_whenTestingTransitive_thenEqualsTransitive() { Car car1 = new Car("Honda", 2020); Car car2 = new Car("Honda", 2020); Car car3 = new Car("Honda", 2020); @@ -51,7 +51,7 @@ void testEquals_Transitive() { } @Test - void testEquals_NotEqual() { + void givenTwoDifferentCarObjects_whenComparingWithEquals_thenEqualsReturnsFalse() { Car car1 = new Car("Honda", 2020); Car car2 = new Car("Toyota", 2020); // Different make @@ -59,7 +59,7 @@ void testEquals_NotEqual() { } @Test - void testEquals_Null() { + void givenANonNullCarObject_whenTestingAgainstNull_thenEqualsReturnsFalse() { Car car1 = new Car("Honda", 2020); // Must return false when compared to null. assertFalse(car1.equals(null), "Must return false for null"); @@ -68,7 +68,7 @@ void testEquals_Null() { // --- hashCode() Tests (from second test block) --- @Test - void testHashCode_EqualObjects() { + void givenTwoEqualCarObjects_whenComparingHashCodes_thenReturnsEqualHashCodes() { Car car1 = new Car("Honda", 2020); Car car2 = new Car("Honda", 2020); @@ -78,7 +78,7 @@ void testHashCode_EqualObjects() { } @Test - void testHashCode_Consistent() { + void givenACarObject_whenTestingHashCodeConsistency_thenReturnsSameHashCodeAcrossMultipleCalls() { Car car = new Car("Honda", 2020); int initialHash = car.hashCode(); @@ -90,7 +90,7 @@ void testHashCode_Consistent() { // --- toString() Test (from third test block) --- @Test - void testToString() { + void givenACarObject_whenTestingToString_thenReturnsExpectedString() { Car car = new Car("Tesla", 2023); String expected = "Car{make='Tesla', year=2023}"; @@ -102,7 +102,7 @@ void testToString() { // --- getClass() Test (from fourth test block) --- @Test - void testGetClass() { + void givenACarObject_whenTestingGetClass_thenReturnsCarClass() { Car car = new Car("Ford", 2015); // The returned Class object must match the Car class. From 1c19c677435087bc36aa88ea1318b901d8697286 Mon Sep 17 00:00:00 2001 From: Deepak Vohra Date: Thu, 23 Oct 2025 17:58:29 -0700 Subject: [PATCH 6/9] Update Car object creation in unit test --- .../java/com/baeldung/objectclassguide/CarObjectUnitTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/objectclassguide/CarObjectUnitTests.java b/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/objectclassguide/CarObjectUnitTests.java index 6c9774d871c1..3aa78233626b 100644 --- a/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/objectclassguide/CarObjectUnitTests.java +++ b/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/objectclassguide/CarObjectUnitTests.java @@ -116,7 +116,7 @@ void givenACarObject_whenTestingGetClass_thenReturnsCarClass() { @DisplayName("Test shallow cloning maintains value equality") void testClone_Success() throws CloneNotSupportedException { // Assuming Car class implements Cloneable and overrides clone() - Car original = new Car(TEST_MAKE, TEST_YEAR); + Car original = new Car("Honda", 2020); Car cloned = (Car) original.clone(); // 1. Should be different objects (reference inequality) From bece77f1a309482faf48362eb189c47fafa19fb0 Mon Sep 17 00:00:00 2001 From: Deepak Vohra Date: Thu, 23 Oct 2025 18:05:29 -0700 Subject: [PATCH 7/9] Remove synchronization tests for Car class Removed tests for wait(), notify(), and notifyAll() methods due to synchronization issues. --- .../objectclassguide/CarObjectUnitTests.java | 48 ------------------- 1 file changed, 48 deletions(-) diff --git a/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/objectclassguide/CarObjectUnitTests.java b/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/objectclassguide/CarObjectUnitTests.java index 3aa78233626b..6091fade5c40 100644 --- a/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/objectclassguide/CarObjectUnitTests.java +++ b/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/objectclassguide/CarObjectUnitTests.java @@ -130,54 +130,6 @@ void testClone_Success() throws CloneNotSupportedException { // assertEquals(original.getYear(), cloned.getYear(), "Year field should be identical."); } - // --- wait(), notify(), notifyAll() Tests (Synchronization - from fifth test block) --- - - @Test - @DisplayName("Test wait() throws IllegalMonitorStateException when not synchronized") - void testWait_IllegalMonitorState() { - Car car = new Car(TEST_MAKE, TEST_YEAR); - - // Assert that calling wait() without a monitor (synchronized block) throws the expected exception - assertThrows(IllegalMonitorStateException.class, () -> { - car.wait(); - }, "wait() must throw IllegalMonitorStateException when called outside a synchronized block."); - } - - @Test - @DisplayName("Test notify() throws IllegalMonitorStateException when not synchronized") - void testNotify_IllegalMonitorState() { - Car car = new Car(TEST_MAKE, TEST_YEAR); - - // Assert that calling notify() without a monitor (synchronized block) throws the expected exception - assertThrows(IllegalMonitorStateException.class, () -> { - car.notify(); - }, "notify() must throw IllegalMonitorStateException when called outside a synchronized block."); - } - - @Test - @DisplayName("Test notifyAll() throws IllegalMonitorStateException when not synchronized") - void testNotifyAll_IllegalMonitorState() { - Car car = new Car(TEST_MAKE, TEST_YEAR); - - // Assert that calling notifyAll() without a monitor (synchronized block) throws the expected exception - assertThrows(IllegalMonitorStateException.class, () -> { - car.notifyAll(); - }, "notifyAll() must throw IllegalMonitorStateException when called outside a synchronized block."); - } - - @Test - @DisplayName("Test timed wait() inside synchronized block does not throw exception") - void testWait_SynchronizedSuccess() { - Car car = new Car(TEST_MAKE, TEST_YEAR); - - assertDoesNotThrow(() -> { - synchronized (car) { - // Wait for a very short time (1ms) to verify the call is legal - car.wait(1); - } - }, "wait() call inside synchronized block should not throw an exception."); - } - // --- finalize() Test (Conceptual - from fifth test block) --- private static AtomicBoolean finalizedFlag = new AtomicBoolean(false); From 5ed358473a24309d192d3f1d07d36c355e635bd6 Mon Sep 17 00:00:00 2001 From: Deepak Vohra Date: Thu, 23 Oct 2025 18:24:14 -0700 Subject: [PATCH 8/9] Refactor CarObjectUnitTests for clarity and conciseness Refactored JUnit tests for the Car class by removing comments and simplifying assertions. --- .../objectclassguide/CarObjectUnitTests.java | 173 +++--------------- 1 file changed, 26 insertions(+), 147 deletions(-) diff --git a/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/objectclassguide/CarObjectUnitTests.java b/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/objectclassguide/CarObjectUnitTests.java index 6091fade5c40..7f4e7642d9e8 100644 --- a/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/objectclassguide/CarObjectUnitTests.java +++ b/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/objectclassguide/CarObjectUnitTests.java @@ -1,41 +1,25 @@ package com.baeldung.objectclassguide; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.DisplayName; -import static org.junit.jupiter.api.Assertions.*; -import java.util.concurrent.atomic.AtomicBoolean; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotSame; -/** - * Merged JUnit 5 tests for the Car class, focusing on standard - * Object methods (equals, hashCode, toString, getClass) and - * advanced methods (clone, wait/notify, finalize). - * - * NOTE: It is assumed that a 'Car' class exists with 'make' (String) - * and 'year' (int) fields, and correctly implements or overrides - * the Object methods being tested (including a 'getMake' and 'getYear' - * for the clone test, and optionally implements Cloneable). - */ public class CarObjectUnitTests { - private final String TEST_MAKE = "Honda"; - private final int TEST_YEAR = 2020; - - // --- equals() Tests (from first test block) --- - @Test void givenACarObject_whenTestingObjectEqualsItself_thenEqualsReflexive() { Car car1 = new Car("Honda", 2020); - // An object must equal itself. - assertTrue(car1.equals(car1), "Must be reflexive"); + assertTrue(car1.equals(car1)); } @Test void givenTwoCarObjects_whenTestingSymmetric_thenEqualsSymmetric() { Car car1 = new Car("Honda", 2020); Car car2 = new Car("Honda", 2020); - // If car1.equals(car2) is true, then car2.equals(car1) must be true. - assertTrue(car1.equals(car2), "Symmetry part 1"); - assertTrue(car2.equals(car1), "Symmetry part 2"); + assertTrue(car1.equals(car2)); + assertTrue(car2.equals(car1)); } @Test @@ -43,171 +27,66 @@ void givenThreeCarObjects_whenTestingTransitive_thenEqualsTransitive() { Car car1 = new Car("Honda", 2020); Car car2 = new Car("Honda", 2020); Car car3 = new Car("Honda", 2020); - - // If a==b and b==c, then a must equal c. + assertTrue(car1.equals(car2)); assertTrue(car2.equals(car3)); - assertTrue(car1.equals(car3), "Must be transitive"); + assertTrue(car1.equals(car3)); } @Test void givenTwoDifferentCarObjects_whenComparingWithEquals_thenEqualsReturnsFalse() { Car car1 = new Car("Honda", 2020); - Car car2 = new Car("Toyota", 2020); // Different make + Car car2 = new Car("Toyota", 2020); - assertFalse(car1.equals(car2), "Objects with different state should be unequal"); + assertFalse(car1.equals(car2)); } @Test void givenANonNullCarObject_whenTestingAgainstNull_thenEqualsReturnsFalse() { Car car1 = new Car("Honda", 2020); - // Must return false when compared to null. - assertFalse(car1.equals(null), "Must return false for null"); + + assertFalse(car1.equals(null)); } - // --- hashCode() Tests (from second test block) --- - @Test void givenTwoEqualCarObjects_whenComparingHashCodes_thenReturnsEqualHashCodes() { Car car1 = new Car("Honda", 2020); Car car2 = new Car("Honda", 2020); - - // Equal objects MUST have equal hash codes. - assertEquals(car1.hashCode(), car2.hashCode(), - "Equal objects must have identical hash codes"); + + assertEquals(car1.hashCode(), car2.hashCode()); } @Test void givenACarObject_whenTestingHashCodeConsistency_thenReturnsSameHashCodeAcrossMultipleCalls() { Car car = new Car("Honda", 2020); int initialHash = car.hashCode(); - - // If the object's fields haven't changed, hashCode() must return the same value. - assertEquals(initialHash, car.hashCode(), - "hashCode() must be consistent across multiple calls"); + + assertEquals(initialHash, car.hashCode()); } - // --- toString() Test (from third test block) --- - @Test void givenACarObject_whenTestingToString_thenReturnsExpectedString() { Car car = new Car("Tesla", 2023); String expected = "Car{make='Tesla', year=2023}"; - // Check if the output matches the expected formatted string. - assertEquals(expected, car.toString(), - "toString() should return a human-readable representation of the object's state"); + assertEquals(expected, car.toString()); } - // --- getClass() Test (from fourth test block) --- - @Test void givenACarObject_whenTestingGetClass_thenReturnsCarClass() { Car car = new Car("Ford", 2015); - - // The returned Class object must match the Car class. - assertEquals(Car.class, car.getClass(), - "getClass() must return the runtime Class object"); + + assertEquals(Car.class, car.getClass()); } - // --- clone() Test (from fifth test block) --- - @Test - @DisplayName("Test shallow cloning maintains value equality") - void testClone_Success() throws CloneNotSupportedException { - // Assuming Car class implements Cloneable and overrides clone() + void givenACarObject_whenTestingClone_thenCloneSuccess() throws CloneNotSupportedException { Car original = new Car("Honda", 2020); Car cloned = (Car) original.clone(); - - // 1. Should be different objects (reference inequality) - assertNotSame(original, cloned, "The cloned object should be a new instance."); - - // 2. Should have the same values (value equality) - assertEquals(original, cloned, "Cloned object should be equal to the original."); - // Note: The original test block implied the existence of getMake/getYear. - // These are used to verify shallow copy correctness. - // assertEquals(original.getMake(), cloned.getMake(), "Make field should be identical."); - // assertEquals(original.getYear(), cloned.getYear(), "Year field should be identical."); - } - - // --- finalize() Test (Conceptual - from fifth test block) --- - - private static AtomicBoolean finalizedFlag = new AtomicBoolean(false); - - // A nested class that overrides finalize() for demonstration purposes - private static class FinalizableCar extends Car { - public FinalizableCar(String make, int year) { - // Assuming Car has a constructor Car(String, int) - super(make, year); - } - - @Override - protected void finalize() throws Throwable { - try { - finalizedFlag.set(true); - } finally { - super.finalize(); - } - } - } - - @Test - @DisplayName("Conceptual Test for finalize() (Execution is non-deterministic)") - void testFinalize_Conceptual() { - // Reset the flag - finalizedFlag.set(false); - - // Create an object and make it unreachable - new FinalizableCar(TEST_MAKE, TEST_YEAR); - - // Suggest Garbage Collection (Non-deterministic and unreliable for testing) - System.gc(); - - // The assertion for finalizedFlag is commented out as it's non-deterministic. - System.out.println("\n*** finalize() Test Note ***"); - System.out.println("The finalize() method is deprecated and its execution is non-deterministic."); - System.out.println("Current status of finalization flag after System.gc() (Unreliable): " + finalizedFlag.get()); - System.out.println("****************************\n"); - } -} - -// NOTE: The Car class definition is assumed to exist in the environment -// but is not provided here, as the request was only to merge the tests. - -// Example placeholder for the Car class (must be available for the tests to compile): -class Car implements Cloneable { - private final String make; - private final int year; - - public Car(String make, int year) { - this.make = make; - this.year = year; - } - - public String getMake() { return make; } - public int getYear() { return year; } - - // Implementations for the tested methods would go here... - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Car car = (Car) o; - return year == car.year && make.equals(car.make); - } - - @Override - public int hashCode() { - return java.util.Objects.hash(make, year); - } - - @Override - public String toString() { - return "Car{make='" + make + "', year=" + year + "}"; - } - - @Override - protected Object clone() throws CloneNotSupportedException { - return super.clone(); + + assertNotSame(original, cloned); + assertEquals(original, cloned); + assertEquals(original.getMake(), cloned.getMake()); + assertEquals(original.getYear(), cloned.getYear()); } } From ded699180c93b77507594564b17e3e746cf2f062 Mon Sep 17 00:00:00 2001 From: Deepak Vohra Date: Sun, 2 Nov 2025 17:32:01 -0800 Subject: [PATCH 9/9] Fix formatting in toString() method of Car class --- .../src/main/java/com/baeldung/objectclassguide/Car.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/objectclassguide/Car.java b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/objectclassguide/Car.java index 8f88be033632..37978a5b9076 100644 --- a/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/objectclassguide/Car.java +++ b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/objectclassguide/Car.java @@ -59,10 +59,10 @@ public int hashCode() { */ @Override public String toString() { - return "Car{" + - "make='" + make + '\'' + - ", year=" + year + - '}'; + return "Car{" + + "make='" + make + '\'' + + ", year=" + year + + '}'; }