Notice

╠ This is my personal blog and my posts here have nothing to do with my employers or any other association I may have. It is my personal blog for my personal experience, ideas and notes. ╣

Thursday, March 5, 2015

Object utility with null safety


Java Objects utility class with examples

All of Java developers faced NullPointerException during there development phases.
What we  all developers do to prevent this ?
Simple put a null check before using that object.

Finally Java language feels that it can be done bit smart way. They introduced java.util.Objects class. This class is an object utility class with static methods which are null safe or null tolerant methods for some mostly used basic utility class.

public final class java.util.Objects {
  public static boolean equals(java.lang.Object, java.lang.Object);
  public static boolean deepEquals(java.lang.Object, java.lang.Object);
  public static int hashCode(java.lang.Object);
  public static int hash(java.lang.Object...);
  public static java.lang.String toString(java.lang.Object);
  public static java.lang.String toString(java.lang.Object, java.lang.String);
  public static <T> int compare(T, T, java.util.Comparator<? super T>);
  public static <T> T requireNonNull(T);
  public static <T> T requireNonNull(T, java.lang.String);
  public static boolean isNull(java.lang.Object);
  public static boolean nonNull(java.lang.Object);
  public static <T> T requireNonNull(T, java.util.function.Supplier<java.lang.String>);
}

Lets check-out each methods and see what they really do. Before I start, I want you to know that I'm using JDK 8 for my examples.

Equals and DeepEquals


public static boolean equals(java.lang.Object, java.lang.Object);
public static boolean deepEquals(java.lang.Object, java.lang.Object);

Over here we are not interested in implementation of equals method, what I bring into light is when we use equals method during development we generally write if(obj1 != null && obj1.equals(obj2) or if(obj2 != null && obj2.equals(obj1) kind of code to safe guard from NullPointerException. Here in JDK 1.7 in java.util.Objects we have an static utility method by which we can simple check for equals without go for extra null check before invocation of equals method.

Here in Objects.equals(a,b) equals method is invoked on object 'a'.
EqualsTest.java
  1. import java.util.Objects;
  2. public class EqualsTest {
  3. public static void main(String[] args) {
  4. Object a = new Object();
  5. Object b = null;
  6. System.out.println(Objects.equals(a,b));
  7. }
  8. }
Here is source output

false

Here we have another equals method which look deep into the object. Let's see what deepEquals do, deepEquals compare two objects and figure out whether they are same or not. So there is equals method already do the same why do they have deepEquals doing the same job as equals. Interesting deepEquals and equals methods are not exactly same.
Using deepEquals method we can compare both objects and arrays also. When both the arguments are arrays then it uses Arrays.deepEquals0 method to compare each elements of both the arrays.

DeepEqualsTest.java
  1. import java.util.Objects;
  2. public class DeepEqualsTest {
  3. public static void main(String[] args) {
  4. Object obj1 = new Object();
  5. Object obj2 = null;
  6. Object obj3 = obj1;
  7. Object obj4 = new Object();
  8. System.out.println("Is obj1 is equals to obj2 ? " +Objects.deepEquals(obj1, obj2));
  9. System.out.println("Is obj2 is equals to obj3 ? " +Objects.deepEquals(obj2, obj3));
  10. System.out.println("Is obj1 is equals to obj3 ? " +Objects.deepEquals(obj1, obj3));
  11. System.out.println("Is obj1 is equals to obj4 ? " +Objects.deepEquals(obj1, obj4));
  12. int a[] = {1,2,3};
  13. int b[] = {1,2,3};
  14. int c[] = {1,2,3,4};
  15. int d[] = null;
  16. System.out.println("Is array a is equals to b ? " +Objects.deepEquals(a, b));
  17. System.out.println("Is array a is equals to c ? " +Objects.deepEquals(a, c));
  18. System.out.println("Is array d is equals to c ? " +Objects.deepEquals(d, c));
  19. Object objs1[] = {obj1,obj4};
  20. Object objs2[] = {obj3,obj4};
  21. Object objs3[] = null;
  22. Object objs4[] = {obj4};
  23. System.out.println("Is array objs2 is equals to objs1 ? " +Objects.deepEquals(objs2, objs1));
  24. System.out.println("Is array objs3 is equals to objs2 ? " +Objects.deepEquals(objs3, objs2));
  25. System.out.println("Is array objs4 is equals to objs2 ? " +Objects.deepEquals(objs4, objs2));
  26. }
  27. }


Here is source output.
Is obj1 is equals to obj2 ? false
Is obj2 is equals to obj3 ? false
Is obj1 is equals to obj3 ? true
Is obj1 is equals to obj4 ? false
Is array a is equals to b ? true
Is array a is equals to c ? false
Is array d is equals to c ? false
Is array objs2 is equals to objs1 ? true
Is array objs3 is equals to objs2 ? false
Is array objs4 is equals to objs2 ? false


Hash and HashCode


public static int hashCode(java.lang.Object);
public static int hash(java.lang.Object...);

Here also we have two variant of hash code methods as equals.
hashCode method simply return hash code value of the object where as hash method can return hash code value of array of objects and primitive data types.
HashCodeTest.java
  1. import java.util.Objects;
  2. public class HashCodeTest {
  3. public static void main(String[] args) {
  4. Object obj1 = new Object();
  5. Object obj2 = null;
  6. System.out.println("Hash Code value of obj1 is " +Objects.hashCode(obj1));
  7. System.out.println("Hash Code value of obj2 is " +Objects.hashCode(obj2));
  8. Object objs1[] = {obj1,obj2};
  9. int objs2[] = {1,2,3,4};
  10. System.out.println("Hash Code value of object is " +Objects.hash(obj1));
  11. System.out.println("Hash Code value of array of objects is " +Objects.hash(objs1));
  12. System.out.pr int ln("Hash Code value of array of int is " +Objects.hash(objs2));
  13. }
  14. }

Here is the source output

Hash Code value of obj1 is 366712642
Hash Code value of obj2 is 0
Hash Code value of object is  366712673  [Note :- This is not same as 1st line of output]
Hash Code value of array of objects is  -1516809025
Hash Code value of array of int is  1829164731


ToString


public static java.lang.String toString(java.lang.Object);
public static java.lang.String toString(java.lang.Object, java.lang.String);

Here we have two variant of toString one which simply return the toString value of the object where as toString(Object,String) can be used when we required to set something default string in case of object is null.

ToStringTest.java
  1. public class ToStringTest {
  2. public static void main(String[] args) {
  3. Object obj1 = new Object();
  4. Object obj2 = null;
  5. System.out.println("toString value of obj1 is " +Objects.toString(obj1));
  6. System.out.println("toString value of obj2 is " +Objects.toString(obj2));
  7. System.out.println("toString value of obj2 is " +Objects.toString(obj2, "\'sorry it's null\'"));
  8. }
  9. }

Here is the source output

toString value of obj1 is java.lang.Object@15db9742
toString value of obj2 is null
toString value of obj2 is 'sorry it's null' [See default null is returned]

 

Compare

public static <T> int compare(T, T, java.util.Comparator<? super T>);

This is the only static utility method which I found that this method is not null proof, actually developer have to develop a null proof comparator.
It simple compare the objects using your comparator and return value. Wait a minute what I say in previous line is conflicting, when I had written the comparator I have to make sure that it is null proof. So I have to write a special null proof comparator. Now I try reasoned out why they put this static utility method here in this Objects class, as everything need to be done by developer itself. I didn't find anything special about it, let me know if you have anything. 
CompareTest.java
  1. import java.util.Objects;
  2. import java.util.Comparator;
  3. public class CompareTest {
  4. public static void main(String[] args) {
  5. Integer obj1 = Integer.valueOf(1);
  6. Integer obj2 = null;
  7. Integer obj3 = Integer.valueOf(1);
  8. Integer obj4 = Integer.valueOf(2);
  9. WrapperIntegerComparator comparator = new WrapperIntegerComparator();
  10. System.out.println("compare value of "+ obj2 +" with "+ obj1 +" = " +Objects.compare(obj2, obj1, comparator));
  11. System.out.println("compare value of "+ obj4 +" with "+ obj1 +" = " +Objects.compare(obj4, obj1, comparator));
  12. System.out.println("compare value of "+ obj3 +" with "+ obj1 +" = " +Objects.compare(obj3, obj1, comparator));
  13. }
  14. }
  15. // Null proof comparator
  16. class WrapperIntegerComparator implements Comparator<Integer> {
  17. public int compare(Integer x, Integer y) {
  18. if(x == y) {
  19. return 0;
  20. } else if(y == null) {
  21. return 1;
  22. } else if(( x == null) ||(x < y))
  23. return -1;
  24. else
  25. return ((x == y) ? 0 : 1);
  26. }
  27. }


Here is the source output

compare value of null with 1 = -1
compare value of 2 with 1 = 1
compare value of 1 with 1 = 0


RequiredNonNull

public static <T> T requireNonNull(T);
public static <T> T requireNonNull(T, java.lang.String);

These methods behaviour are same of when we try to insert a null value in not null column, it will complain about null value. These methods throw NullPointerException if the parameter is null and the second method add error message of NullPointerException. Let's blew out some NullPointerException.

RequireNonNullTest.java
  1. import java.util.Objects;
  2. public class RequireNonNullTest {
  3. public static void main(String[] args) {
  4. String name1 = "Andy";
  5. String name2 = null;
  6. System.out.println("1st person name is "+ Objects.requireNonNull(name1));
  7. System.out.println("2nd person name is "+ Objects.requireNonNull(name2,"There is no person of this name"));
  8. }
  9. }

Here is the source output

1st person name is Andy
Exception in thread "main" java.lang.NullPointerException: There is no person of this name
    at java.util.Objects.requireNonNull(Objects.java:228)
    at com.ch1.RequireNonNullTest.main(RequireNonNullTest.java:20)


IsNull and NonNull

public static boolean isNull(java.lang.Object);
public static boolean nonNull(java.lang.Object);

Now without confusing yourself and other developer you can check for object is null or not. I am not really impressed by the 'non' word, they could have used 'not' instead of that don't know what stop them or why they like 'non' instead of 'not'.

isNull method return true if object is null else false.
nonNull methos return true if object is not null else false.

TestForNull.java
  1. import java.util.Objects;
  2. public class TestForNull {
  3. public static void main(String[] args) {
  4. String name1 = "Andy";
  5. String name2 = null;
  6. System.out.println(name1 +" isNull "+ Objects.isNull(name1));
  7. System.out.println(name2 +" isNull "+ Objects.isNull(name2));
  8. System.out.println(name1 +" nonNull "+ Objects.nonNull(name1));
  9. System.out.println(name2 +" nonNull "+ Objects.nonNull(name2));
  10. }
  11. }


Here is the source output

Andy isNull false
null isNull true
Andy nonNull true
null nonNull false



public static <T> T requireNonNull(T, java.util.function.Supplier<java.lang.String>) 

This particular API is added in Java 8 but it does the same job as previous requireNonNull method does.

RequireNonNullWithSupplierTest.java
  1. import java.util.Objects;
  2. import java.util.function.Supplier;
  3. public class RequireNonNullWithSupplierTest {
  4. public static void main(String[] args) {
  5. String name1 = "Andy";
  6. String name2 = null;
  7. MessageSupplier msgSupplier = new MessageSupplier();
  8. System.out.println("1st person name is "+ Objects.requireNonNull(name1, msgSupplier));
  9. System.out.println("2nd person name is "+ Objects.requireNonNull(name2, msgSupplier));
  10. }
  11. }
  12. class MessageSupplier implements Supplier<String> {
  13. @Override
  14. public String get() {
  15. return "\'This person name not found.\'";
  16. }
  17. }

Here is the source output

1st person name is Andy
Exception in thread "main" java.lang.NullPointerException: 'This person name not found.'
    at java.util.Objects.requireNonNull(Objects.java:228)
    at com.ch1.RequireNonNullWithSupplierTest.main(RequireNonNullWithSupplierTest.java:24)

Some regularly used methods with null check, I think developers are going to love it. 

Happy Coding :)