0

In my codebase, I found a class like this:

public final class Klass
{
   private static final long LONG_NUMBER = 10.0;

   private Klass() {}

   public static double calcSomethingUsingLongNumberAndParam(double param)
   {
     ...
     return something;
   }
}

My IDE (IntelliJ IDEA) offers one 'improvement' to this class - change it to an enum. As a test, I made the change, and noted no other refactors done on any of the member fields or methods, not to any calls to the static methods contained.

Here is the generated Enum:

public enum Klass
{
   ;
   private static final long LONG_NUMBER = 10.0;

   private Klass() {}

   public static double calcSomethingUsingLongNumberAndParam(double param)
   {
     ...
     return something;
   }
}

Is there a benefit to changing a final class to an enum, or is this a quirk of the IDE?

AerusDar
  • 210
  • 6
  • 22
  • Can you show what is the generated enum looks like? – Enzokie May 03 '18 at 05:36
  • You might as well make this an `interface`, actually, since it only has a `static` field and no member methods. – daniu May 03 '18 at 05:41
  • @daniu no, interfaces are for types. What would it mean for there to be an instance of `Klass`? (There is an item in *Effective Java* specifically about this). – Andy Turner May 03 '18 at 06:26

2 Answers2

0

My answer originally said that sure there are benefits, enums supersede old-style POJO singletons (which this is a special case of) in almost every way. However, it depends a bit on the use case and actual code involved. If you just replace "final class" with "enum", as IDE seems to be doing in this case, the benefits are minimal. Also, one of the main benefits of using enum is a better type checking for finite values, but since you seem to be using only a single, numeric value and it is private, it's of no benefit here.

Pros on using an enum vs. constant utility class:

  • Enums get away with almost the same functionality with less code - you don't need to declare functions or values as static, nor do you need a private constructor, which are just boilerplate that enum offers out of the box
  • it is immediately clear with enums that they are not meant to be instantiated, whereas for a class like this, it might need more investigation and a look at its details as a whole
  • with a class like this it is far easier for someone updating the code to mess up the singleton pattern by accident if he/she doesn't notice it's meant to be that way

Cons:

  • enum class itself are effectively final, but their internal design depends on the possibility to make subclasses for the enum values, so their protection from subclassing seems to me a bit hacky.

So, if this class is part of interface offered as an external library and we can be quite confident no one will change its own implementation, it is actually a bit more safe than using an enum here. However, if this code is maintained (especially by different developers) - and any code should be, I would argue an enum has more pros to offer, as it more clearly communicates its intent. Even the only con I could come up with, removal of protection from subclassing, seems quite marginal as enums are effectively final anyway outside their defining class.

For more discussion on the benefits of enums, see What are enums and why are they useful?. There is also another discussion on the benefits of having a final keyword in a constant utility class such as yours: Final Keyword in Constant utility class - the conclusion I get from that discussion is that the only benefit is that it is explicitly forbidden to subclass it, which wouldn't work anyway since you wouldn't be able to override the static stuff.

TLDR; recommendation to replace with enum seems reasonable, at least if you omit the things you don't have to explicitly declare with enums. However the differences are related to the readability and maintainability, not any difference in behaviour.

eis
  • 51,991
  • 13
  • 150
  • 199
  • "enum class itself cannot be final, as their internal design depends on the possibility to make subclasses for the enum values. Thus, you don't get the protection from subclassing." Eh? You can't extend enums, or their values. – Andy Turner May 03 '18 at 06:28
  • @AndyTurner you can't extend them outside the enum class definition. Its members do extend the enum. But I did write it in a confusing way. I'll try to make it better... – eis May 03 '18 at 07:55
0

There is no outright benefit to changing this class to an enum.

The only thing it affords you is the ability to omit the private constructor (and the final on the class).

But you'd also need either a single value (that you don't need), or just have a random hanging ; to separate the (empty) value list from the rest of the class body.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243