Published on Sat Feb 15 2025 10:00:00 GMT+0000 (Coordinated Universal Time) by Purusothaman Ramanujam
Object Utilities in Apache Commons Lang
Introduction
Working with objects in Java often involves handling null values, comparing objects safely, and providing default values. Apache Commons Lang’s ObjectUtils
provides a comprehensive set of utilities that make object operations safer, more convenient, and more robust.
In this comprehensive guide, you’ll learn how to use ObjectUtils
effectively with detailed examples and real-world use cases.
Adding Apache Commons Lang to Your Project
Maven Dependency
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.13.0</version></dependency>
Gradle Dependency
implementation 'org.apache.commons:commons-lang3:3.13.0'
Basic Object Operations
Null-Safe Operations
One of the biggest advantages of ObjectUtils
is its null-safe operations:
import org.apache.commons.lang3.ObjectUtils;
public class ObjectUtilsBasics { public static void main(String[] args) { String str1 = "Hello"; String str2 = null; Integer num1 = 42; Integer num2 = null;
// Null-safe default values System.out.println(ObjectUtils.defaultIfNull(str1, "Default")); // "Hello" System.out.println(ObjectUtils.defaultIfNull(str2, "Default")); // "Default" System.out.println(ObjectUtils.defaultIfNull(num1, 0)); // 42 System.out.println(ObjectUtils.defaultIfNull(num2, 0)); // 0
// Null-safe first non-null value System.out.println(ObjectUtils.firstNonNull(str1, str2, "Default")); // "Hello" System.out.println(ObjectUtils.firstNonNull(str2, "Default", "Backup")); // "Default" System.out.println(ObjectUtils.firstNonNull(null, null, "Last Resort")); // "Last Resort"
// Check if object is null System.out.println(ObjectUtils.isEmpty(str1)); // false System.out.println(ObjectUtils.isEmpty(str2)); // true System.out.println(ObjectUtils.isEmpty("")); // true System.out.println(ObjectUtils.isEmpty(" ")); // false (not empty, has whitespace) }}
Object Comparison
public class ObjectComparison { public static void main(String[] args) { String str1 = "Hello"; String str2 = "Hello"; String str3 = "World"; String str4 = null;
// Null-safe equals System.out.println(ObjectUtils.equals(str1, str2)); // true System.out.println(ObjectUtils.equals(str1, str3)); // false System.out.println(ObjectUtils.equals(str1, str4)); // false System.out.println(ObjectUtils.equals(str4, str4)); // true (both null)
// Null-safe not equals System.out.println(ObjectUtils.notEqual(str1, str2)); // false System.out.println(ObjectUtils.notEqual(str1, str3)); // true System.out.println(ObjectUtils.notEqual(str1, str4)); // true
// Compare with null safety System.out.println(ObjectUtils.compare(str1, str2)); // 0 (equal) System.out.println(ObjectUtils.compare(str1, str3)); // negative (str1 < str3) System.out.println(ObjectUtils.compare(str3, str1)); // positive (str3 > str1) System.out.println(ObjectUtils.compare(str1, str4)); // positive (non-null > null) System.out.println(ObjectUtils.compare(str4, str1)); // negative (null < non-null) }}
Advanced Object Operations
Object Identity and Hash Code
public class ObjectIdentity { public static void main(String[] args) { String str1 = "Hello"; String str2 = "Hello"; String str3 = new String("Hello"); String str4 = null;
// Identity hash code (null-safe) System.out.println(ObjectUtils.identityToString(str1)); // java.lang.String@<hashcode> System.out.println(ObjectUtils.identityToString(str4)); // null
// Hash code (null-safe) System.out.println(ObjectUtils.hashCode(str1)); // hash code of str1 System.out.println(ObjectUtils.hashCode(str4)); // 0 (for null)
// Multiple hash codes System.out.println(ObjectUtils.hashCodeMulti(str1, str2, str3)); // combined hash code
// Clone (if cloneable) try { String cloned = ObjectUtils.clone(str1); System.out.println("Cloned: " + cloned); } catch (Exception e) { System.out.println("Clone failed: " + e.getMessage()); } }}
Object Validation
public class ObjectValidation { public static void main(String[] args) { String validString = "Hello"; String nullString = null; String emptyString = ""; String whitespaceString = " ";
// Check if object is not null System.out.println(ObjectUtils.isNotEmpty(validString)); // true System.out.println(ObjectUtils.isNotEmpty(nullString)); // false System.out.println(ObjectUtils.isNotEmpty(emptyString)); // false System.out.println(ObjectUtils.isNotEmpty(whitespaceString)); // true
// Check if object is null System.out.println(ObjectUtils.isNull(validString)); // false System.out.println(ObjectUtils.isNull(nullString)); // true
// Check if object is not null System.out.println(ObjectUtils.isNotNull(validString)); // true System.out.println(ObjectUtils.isNotNull(nullString)); // false
// Validate with custom predicate System.out.println(ObjectUtils.allNotNull(validString, "World", "Java")); // true System.out.println(ObjectUtils.allNotNull(validString, nullString, "Java")); // false System.out.println(ObjectUtils.anyNotNull(validString, nullString, "Java")); // true System.out.println(ObjectUtils.anyNotNull(nullString, null, null)); // false }}
Collection and Array Operations
Array Utilities
import java.util.Arrays;
public class ArrayOperations { public static void main(String[] args) { String[] array1 = {"Hello", "World"}; String[] array2 = {"Java", "Programming"}; String[] nullArray = null;
// Null-safe array operations System.out.println(ObjectUtils.isEmpty(array1)); // false System.out.println(ObjectUtils.isEmpty(nullArray)); // true System.out.println(ObjectUtils.isEmpty(new String[0])); // true
// Array length (null-safe) System.out.println(ObjectUtils.length(array1)); // 2 System.out.println(ObjectUtils.length(nullArray)); // 0
// Array comparison System.out.println(ObjectUtils.equals(array1, array1)); // true System.out.println(ObjectUtils.equals(array1, array2)); // false System.out.println(ObjectUtils.equals(array1, nullArray)); // false
// Array concatenation String[] combined = ObjectUtils.addAll(array1, array2); System.out.println(Arrays.toString(combined)); // [Hello, World, Java, Programming]
// Clone array String[] cloned = ObjectUtils.clone(array1); System.out.println(Arrays.toString(cloned)); // [Hello, World] System.out.println(cloned != array1); // true (different objects) }}
Collection Utilities
import java.util.ArrayList;import java.util.List;import java.util.Arrays;
public class CollectionOperations { public static void main(String[] args) { List<String> list1 = Arrays.asList("Hello", "World"); List<String> list2 = Arrays.asList("Java", "Programming"); List<String> nullList = null;
// Null-safe collection operations System.out.println(ObjectUtils.isEmpty(list1)); // false System.out.println(ObjectUtils.isEmpty(nullList)); // true System.out.println(ObjectUtils.isEmpty(new ArrayList<>())); // true
// Collection size (null-safe) System.out.println(ObjectUtils.size(list1)); // 2 System.out.println(ObjectUtils.size(nullList)); // 0
// Collection comparison System.out.println(ObjectUtils.equals(list1, list1)); // true System.out.println(ObjectUtils.equals(list1, list2)); // false
// Merge collections List<String> merged = new ArrayList<>(); merged.addAll(list1); merged.addAll(list2); System.out.println(merged); // [Hello, World, Java, Programming] }}
Real-World Examples
Configuration Management
import java.util.HashMap;import java.util.Map;
public class ConfigurationManager { public static class Config { private String databaseUrl; private Integer port; private Boolean debug; private String apiKey;
public Config(String databaseUrl, Integer port, Boolean debug, String apiKey) { this.databaseUrl = databaseUrl; this.port = port; this.debug = debug; this.apiKey = apiKey; }
@Override public String toString() { return String.format("Config{dbUrl='%s', port=%d, debug=%s, apiKey='%s'}", databaseUrl, port, debug, apiKey); } }
public static Config createConfig(String dbUrl, Integer port, Boolean debug, String apiKey) { // Use ObjectUtils to provide defaults for null values String safeDbUrl = ObjectUtils.defaultIfNull(dbUrl, "jdbc:mysql://localhost:3306/mydb"); Integer safePort = ObjectUtils.defaultIfNull(port, 8080); Boolean safeDebug = ObjectUtils.defaultIfNull(debug, false); String safeApiKey = ObjectUtils.defaultIfNull(apiKey, "default-key");
return new Config(safeDbUrl, safePort, safeDebug, safeApiKey); }
public static void main(String[] args) { // Valid configuration Config config1 = createConfig("jdbc:mysql://localhost:3306/prod", 9090, true, "prod-key"); System.out.println(config1);
// Partial configuration (uses defaults) Config config2 = createConfig(null, null, null, null); System.out.println(config2);
// Mixed configuration Config config3 = createConfig("jdbc:mysql://localhost:3306/test", null, true, null); System.out.println(config3); }}
Data Validation
public class DataValidator { public static class User { private String name; private String email; private Integer age;
public User(String name, String email, Integer age) { this.name = name; this.email = email; this.age = age; }
@Override public String toString() { return String.format("User{name='%s', email='%s', age=%d}", name, email, age); } }
public static boolean isValidUser(User user) { if (ObjectUtils.isEmpty(user)) { return false; }
// Check if all required fields are present return ObjectUtils.allNotNull(user.name, user.email, user.age) && !user.name.trim().isEmpty() && user.email.contains("@") && user.age >= 0 && user.age <= 150; }
public static User createValidUser(String name, String email, Integer age) { // Validate and provide defaults String safeName = ObjectUtils.defaultIfNull(name, "Unknown"); String safeEmail = ObjectUtils.defaultIfNull(email, "unknown@example.com"); Integer safeAge = ObjectUtils.defaultIfNull(age, 18);
return new User(safeName, safeEmail, safeAge); }
public static void main(String[] args) { // Valid user User validUser = new User("John Doe", "john@example.com", 25); System.out.println("Valid user: " + isValidUser(validUser));
// Invalid user (null values) User invalidUser = new User(null, null, null); System.out.println("Invalid user: " + isValidUser(invalidUser));
// User with defaults User defaultUser = createValidUser(null, null, null); System.out.println("Default user: " + defaultUser); }}
API Response Handling
import java.util.HashMap;import java.util.Map;
public class ApiResponseHandler { public static class ApiResponse { private Object data; private String message; private Integer statusCode;
public ApiResponse(Object data, String message, Integer statusCode) { this.data = data; this.message = message; this.statusCode = statusCode; }
@Override public String toString() { return String.format("ApiResponse{data=%s, message='%s', statusCode=%d}", data, message, statusCode); } }
public static ApiResponse createResponse(Object data, String message, Integer statusCode) { // Use ObjectUtils to handle null values gracefully Object safeData = ObjectUtils.defaultIfNull(data, new HashMap<>()); String safeMessage = ObjectUtils.defaultIfNull(message, "Success"); Integer safeStatusCode = ObjectUtils.defaultIfNull(statusCode, 200);
return new ApiResponse(safeData, safeMessage, safeStatusCode); }
public static boolean isSuccessfulResponse(ApiResponse response) { if (ObjectUtils.isEmpty(response)) { return false; }
return ObjectUtils.isNotNull(response.statusCode) && response.statusCode >= 200 && response.statusCode < 300; }
public static void main(String[] args) { // Successful response ApiResponse success = createResponse("Data", "Success", 200); System.out.println("Success response: " + isSuccessfulResponse(success));
// Error response ApiResponse error = createResponse(null, "Error", 500); System.out.println("Error response: " + isSuccessfulResponse(error));
// Response with defaults ApiResponse defaultResponse = createResponse(null, null, null); System.out.println("Default response: " + defaultResponse); }}
Performance Considerations
When to Use ObjectUtils vs Standard Java Methods
public class PerformanceComparison { public static void main(String[] args) { // Use ObjectUtils for null-safe operations ObjectUtils.defaultIfNull("value", "default"); // Safe
// Use ObjectUtils for multiple null checks ObjectUtils.allNotNull("a", "b", "c"); // Convenient
// Use standard Java methods for simple operations "Hello".equals("Hello"); // More efficient for non-null values
// Use ObjectUtils for complex object handling ObjectUtils.firstNonNull(null, null, "default"); // Convenient }}
Best Practices
- Always use null-safe methods when dealing with user input or external data
- Use
defaultIfNull()
for providing fallback values instead of manual null checks - Use
firstNonNull()
for multiple fallback options in order of preference - Use
allNotNull()
andanyNotNull()
for validation instead of manual checks - Consider performance for frequently called methods in loops
- Use appropriate methods for your specific use case
Common Pitfalls
public class CommonPitfalls { public static void main(String[] args) { // Pitfall 1: Not using null-safe methods String str = null; // str.equals("test"); // Throws NullPointerException ObjectUtils.equals(str, "test"); // Safe, returns false
// Pitfall 2: Manual null checking instead of utilities String value = null; String result; if (value != null) { result = value; } else { result = "default"; } // vs String betterResult = ObjectUtils.defaultIfNull(value, "default");
// Pitfall 3: Not handling empty collections List<String> list = null; // list.size(); // Throws NullPointerException ObjectUtils.size(list); // Safe, returns 0
// Pitfall 4: Not using appropriate validation methods String[] array = {"a", "b", null, "d"}; // Manual check for all non-null boolean allValid = true; for (String item : array) { if (item == null) { allValid = false; break; } } // vs boolean betterCheck = ObjectUtils.allNotNull(array); }}
Conclusion
ObjectUtils
from Apache Commons Lang provides a robust set of utilities that make object operations safer, more convenient, and more powerful. By understanding these methods and their proper usage, you can write cleaner, more maintainable code that handles edge cases gracefully.
The key benefits include:
- Null safety - No more NullPointerExceptions
- Default values - Graceful handling of null values
- Convenience - Less boilerplate code for common operations
- Consistency - Standardized object handling patterns
- Performance - Optimized implementations
Start incorporating ObjectUtils
into your projects and see how it simplifies your object handling code!
Resources
Written by Purusothaman Ramanujam
← Back to blog