What are the downsides of implementing a singleton with Java’s enum?

Traditionally, a singleton is usually implemented as

public class Foo1
{
    private static final Foo1 INSTANCE = new Foo1();

    public static Foo1 getInstance(){ return INSTANCE; }

    private Foo1(){}

    public void doo(){ ... }
}

With Java’s enum, we can implement a singleton as

public enum Foo2
{
    INSTANCE;

    public void doo(){ ... }
}

As awesome as the 2nd version is, are there any downsides to it?

(I gave it some thoughts and I’ll answer my own question; hopefully you have better answers)

1

Some problems with enum singletons:

Committing to an implementation strategy

Typically, “singleton” refers to an implementation strategy, not an API specification. It is very rare for Foo1.getInstance() to publicly declare that it’ll always return the same instance. If needed, the implementation of Foo1.getInstance() can evolve, for example, to return one instance per thread.

With Foo2.INSTANCE we publicly declare that this instance is the instance, and there’s no chance to change that. The implementation strategy of having a single instance is exposed and committed to.

This problem is not crippling. For example, Foo2.INSTANCE.doo() can rely on a thread local helper object, to effectively have a per-thread instance.

Extending Enum class

Foo2 extends a super class Enum<Foo2>. We usually want to avoid super classes; especially in this case, the super class forced on Foo2 has nothing to do with what Foo2 is supposed to be. That is a pollution to the type hierarchy of our application. If we really want a super class, usually it’s an application class, but we can’t, Foo2‘s super class is fixed.

Foo2 inherits some funny instance methods like name(), cardinal(), compareTo(Foo2), which are just confusing to Foo2‘s users. Foo2 can’t have its own name() method even if that method is desirable in Foo2‘s interface.

Foo2 also contains some funny static methods

    public static Foo2[] values() { ... }
    public static Foo2 valueOf(String name) { ... }
    public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name)

which appears to be nonsensical to users. A singleton usually shouldn’t have pulbic static methods anyway (other than the getInstance())

Serializability

It is very common for singletons to be stateful. These singletons generally should not be be serializable. I can’t think of any realistic example where it makes sense to transport a stateful singleton from one VM to another VM; a singleton means “unique within a VM”, not “unique in the universe”.

If serialization really does make sense for a stateful singleton, the singleton should explicitly and precisely specify what does it means to deserialize a singleton in another VM where a singleton of the same type may already exist.

Foo2 automatically commits to a simplistic serialization/deserialization strategy. That is just an accident waiting to happen. If we have a tree of data conceptually referencing a state variable of Foo2 in VM1 at t1, through serialization/deserialization the value becomes a different value – the value of the same variable of Foo2 in VM2 at t2, creating a hard to detect bug. This bug won’t happen to the unserializable Foo1 silently.

Restrictions of coding

There are things that can be done in normal classes, but forbidden in enum classes. For example, accessing a static field in the constructor. The programmer has to be more careful since he’s working in a special class.

Conclusion

By piggybacking on enum, we save 2 lines of code; but the price is too high, we have to carry all the baggages and restrictions of enums, we inadvertently inherit “features” of enum that have unintended consequences. The only alleged advantage – automatic serializability – turns out to be a disadvantage.

13

An enum instance is dependant on the class loader. ie if you have a second class loader that does not have the first class loader as a parent loading the same enum class you can get multiple instances in memory.


Code Sample

Create the following enum, and put its .class file into a jar by itself. ( of course the jar will have the correct package/folder structure )

package mad;
public enum Side {
  RIGHT, LEFT;
}

Now run this test, making sure that there is no copies of the above enum on the class path:

@Test
public void testEnums() throws Exception
{
    final ClassLoader root = MadTest.class.getClassLoader();

    final File jar = new File("path to jar"); // Edit path
    assertTrue(jar.exists());
    assertTrue(jar.isFile());

    final URL[] urls = new URL[] { jar.toURI().toURL() };
    final ClassLoader cl1 = new URLClassLoader(urls, root);
    final ClassLoader cl2 = new URLClassLoader(urls, root);

    final Class<?> sideClass1 = cl1.loadClass("mad.Side");
    final Class<?> sideClass2 = cl2.loadClass("mad.Side");

    assertNotSame(sideClass1, sideClass2);

    assertTrue(sideClass1.isEnum());
    assertTrue(sideClass2.isEnum());
    final Field f1 = sideClass1.getField("RIGHT");
    final Field f2 = sideClass2.getField("RIGHT");
    assertTrue(f1.isEnumConstant());
    assertTrue(f2.isEnumConstant());

    final Object right1 = f1.get(null);
    final Object right2 = f2.get(null);
    assertNotSame(right1, right2);
}

And we now have two objects representing the “same” enum value.

I agree that this is a rare and contrived corner case, and almost always an enum can be used for a java singleton. I do it myself. But the question asked about potential downsides and this note of caution is worth knowing about.

5

enum pattern can’t be used for any Class that would throw an exception in the constructor. If this is required, use a factory:

class Elvis {
    private static Elvis self = null;
    private int age;

    private Elvis() throws Exception {
        ...
    }

    public synchronized Elvis getInstance() throws Exception {
        return self != null ? self : (self = new Elvis());
    }

    public int getAge() {
        return age;
    }        
}

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật