What's the best practice for creating the Utility (which do not hold any state) classes in Java.
In my opinion the best way is to omit utility classes whenever possible.
A utility class reverses the idea of object-oriented programming. When you come to the point that you need a new method you usually add it to the class with the highest cohesion. This means to the class that holds most of the information the method needs. The other information will be passed into the method as parameters. If the parameter list gets too long it is often an indicator for a misplaced method.
There are rare situations when you really need a utility class to provide a method for some type. E.g.
- if you can't add the method to the source code, because you do not own it (But you might either create a wrapper or subclass it)
- if a class that needs the additional method is final and you don't own the source code (e.g. StringUtility)
In most of the cases we end up creating static methods for such tasks. Other possible way could be "create the singleton objects" for performing this operation.
What should be the design consideration when requirement is the code should be easily unit testable?
If you take a look at utility classes from a unit testability perspective and you want to be able to mock the utiltiy class you should use the singleton, because object references can be replaced.
Either by changing the singleton instance reference (the static variable) or at the client side by using an object field. E.g.
private SomeUtility someUtility = SomeUtiltiy.INSTANCE;
public void someMethod(...){
// Can be replaced by changing the someUtility reference
someUtility.doSomething(....);
// A static call like
// SomeUtility.doSomething(...);
// can not be easily replaced.
}
Static method calls are hard to replace. Some test frameworks like powermock support mocking of static calls by rewriting the client bytecode. But I think that those frameworks were designed to support unit testing of bad legacy code. If you need powermock for new code you should rethink your design.