Java best practice: Class with only static methods

JavaStaticSingletonNio

Java Problem Overview


I have an application where I have a class called PlausibilityChecker. This class has only static methods, like checkZipcodeFormat or checkMailFormat. I use them in my GUI classes to check the input before sending it to the lower layer.

Is this good practice? I thought I'd go with only static methods so that I don't have to care about passing an instance to the GUI classes or having an instance field in each gui class that doesn't reference a gui object.

I noticed that the Files class of Java NIO has only static methods so I assume this can't be that horribly wrong.

Java Solutions


Solution 1 - Java

I would say you're doing it right. Apart of that, some advices for your utility class:

  • Make sure it doesn't have any state. This is, there's no field in the class unless it's declared static final. Also, make sure this field is immutable as well e.g. Strings.
  • Make sure it cannot be a super class of other classes. Make the class final so other programmers cannot extend it.
  • This one is debatable, but you may declare a no-arg constructor private, so no other class could create an instance of your utility class (using reflection or something similar will do, but there's no need to go that protective with the class). Why you may not do this? Well, this is the strange case where you want/need to inject an instance of the utility class e.g. through an interface rather than directly using it along your class. Here's an example of this. This design is really odd but may happen (as shown in the link above), but if you will not run in such case, the best advice is to keep the constructor private.

There are lot of libraries that provide utility classes in order to help us programmers with our work. One of the most known is Apache Common set of libraries. It's open source and you can check the code to see how they design these utility classes in order to create yours. (DISCLAIMER: I do not work or support these libraries, I'm a happy user of them)

Important Note: Avoid using a singleton for your utility class.

Solution 2 - Java

In Java 8 you can now change your static utility classes to interfaces with static implementations. This eliminates the need for making the class final and having to provide a private constructor. It's as simple as changing 'class' to 'interface' and removing the final word if you have it (all interfaces are abstract so they cannot be final). Since interface methods are always public you can remove any public scope from them. If you have a private constructor then remove that as well (you can't compile an interface with a constructor since they can't be instantiated). It's less code and looks cleaner. You won't have to refactor any classes that already use it.

Solution 3 - Java

Don't worry about subclassing or instantiation. The following utility classes in JDK can be subclassed or instantiated, yet nobody has misused them in all those years. People are not that stupid.

java.beans.Beans
java.beans.PropertyEditorManager
java.lang.invoke.LambdaMetafactory
java.lang.reflect.Modifier
java.net.URLDecoder                                   ...but not URLEncoder:)
javax.management.DefaultLoaderRepository
javax.management.Query
javax.management.loading.DefaultLoaderRepository
javax.management.relation.RoleStatus
javax.print.ServiceUI
javax.swing.UIManager
javax.swing.plaf.basic.BasicBorders
javax.swing.plaf.basic.BasicGraphicsUtils
javax.swing.plaf.basic.BasicHTML
javax.swing.plaf.basic.BasicIconFactory
javax.swing.plaf.metal.MetalBorders
javax.swing.plaf.metal.MetalIconFactory
javax.swing.text.Utilities
javax.swing.text.html.HTML

However, as a public API, you do want to suppress the default constructor, otherwise there is an undocumented constructor on the javadoc page which is awkward and confusing. For your own in-house APIs, it doesn't matter, nobody cares.

There is no reason to suppress subclassing though. If anyone wants to subclass a utility class, for whatever reason, let him. Of course, private constructor will suppress subclassing as a side effect.


In java8, there are more design possibilities to consider -

An interface with all static methods - this is just as good as a class with all static methods. Neither interface nor class is designed for this purpose, so either one is OK. However, don't expect to inherit these static methods in subtypes of the interface - interface static methods are not inheritable. One plus point for using interface is that we don't need to suppress the default constructor from appearing on javadoc.

An interface with all default methods - accessed through inheritance. This is interesting but problematic in general (the inheritance works only in non-static context). But it might be a better option in some API designs, for example, this html builder API.

Solution 4 - Java

Why should it not be good practice if you just have methods which provides "tools" to other classes this is fine.

Solution 5 - Java

Classes with only static methods is a common pattern in Java for utility methods. Examples in the standard library include Files, Collections, and Executors.

For such utility classes, it's a good idea to make sure that your class cannot be instantiated, to make the intent of the class clear. You can do so by explicitly declaring a private constructor. See Item 4: Enforce noninstantiability with a private constructor in "Effective Java" by Josh Bloch for details.

Solution 6 - Java

Singleton are ok, depending on the context.

For testing purposes, you may want to mock out references to singletons to avoid side effects during unit tests. In that case, it probably makes sense to use a dependency injection framework such as Spring to handle the creation of the instance and use regular methods which can be overridden instead of static methods.

If you still plan to use static methods, ensure that the calls are thread-safe if used in a multi-threaded context. (e.g. double-checked locking).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser3629892View Question on Stackoverflow
Solution 1 - JavaLuiggi MendozaView Answer on Stackoverflow
Solution 2 - JavaafenknerView Answer on Stackoverflow
Solution 3 - JavaZhongYuView Answer on Stackoverflow
Solution 4 - JavaExar666KunView Answer on Stackoverflow
Solution 5 - JavamarkuskView Answer on Stackoverflow
Solution 6 - JavaJin KimView Answer on Stackoverflow