Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.baeldung.objectclassguide;

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();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package com.baeldung.objectclassguide;

import org.junit.jupiter.api.Test;
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;

public class CarObjectUnitTests {

@Test
void givenACarObject_whenTestingObjectEqualsItself_thenEqualsReflexive() {
Car car1 = new Car("Honda", 2020);
assertTrue(car1.equals(car1));
}

@Test
void givenTwoCarObjects_whenTestingSymmetric_thenEqualsSymmetric() {
Car car1 = new Car("Honda", 2020);
Car car2 = new Car("Honda", 2020);
assertTrue(car1.equals(car2));
assertTrue(car2.equals(car1));
}

@Test
void givenThreeCarObjects_whenTestingTransitive_thenEqualsTransitive() {
Car car1 = new Car("Honda", 2020);
Car car2 = new Car("Honda", 2020);
Car car3 = new Car("Honda", 2020);

assertTrue(car1.equals(car2));
assertTrue(car2.equals(car3));
assertTrue(car1.equals(car3));
}

@Test
void givenTwoDifferentCarObjects_whenComparingWithEquals_thenEqualsReturnsFalse() {
Car car1 = new Car("Honda", 2020);
Car car2 = new Car("Toyota", 2020);

assertFalse(car1.equals(car2));
}

@Test
void givenANonNullCarObject_whenTestingAgainstNull_thenEqualsReturnsFalse() {
Car car1 = new Car("Honda", 2020);

assertFalse(car1.equals(null));
}

@Test
void givenTwoEqualCarObjects_whenComparingHashCodes_thenReturnsEqualHashCodes() {
Car car1 = new Car("Honda", 2020);
Car car2 = new Car("Honda", 2020);

assertEquals(car1.hashCode(), car2.hashCode());
}

@Test
void givenACarObject_whenTestingHashCodeConsistency_thenReturnsSameHashCodeAcrossMultipleCalls() {
Car car = new Car("Honda", 2020);
int initialHash = car.hashCode();

assertEquals(initialHash, car.hashCode());
}

@Test
void givenACarObject_whenTestingToString_thenReturnsExpectedString() {
Car car = new Car("Tesla", 2023);
String expected = "Car{make='Tesla', year=2023}";

assertEquals(expected, car.toString());
}

@Test
void givenACarObject_whenTestingGetClass_thenReturnsCarClass() {
Car car = new Car("Ford", 2015);

assertEquals(Car.class, car.getClass());
}

@Test
void givenACarObject_whenTestingClone_thenCloneSuccess() throws CloneNotSupportedException {
Car original = new Car("Honda", 2020);
Car cloned = (Car) original.clone();

assertNotSame(original, cloned);
assertEquals(original, cloned);
assertEquals(original.getMake(), cloned.getMake());
assertEquals(original.getYear(), cloned.getYear());
}
}