24

I read a lot on stackoverflow regarding the creation of singleton classes using enum. I must have missed something because i can't reach the INSTANCE anywhere.

this is my code:

public class UserActivity {

    private DataSource _dataSource;
    private JdbcTemplate _jdbcTemplate;

    static enum Singleton {
        INSTANCE;

        private static final UserActivity singleton = new UserActivity();

        public UserActivity getSingleton() {
            return singleton;
        }
    }

    public UserActivity() {
        this._dataSource = MysqlDb.getInstance().getDataSource();
        this._jdbcTemplate = new JdbcTemplate(this._dataSource);
    }

    public void dostuff() {
     ...
    }
}

and outside I'm trying to do

UserActivity.INSTANCE.getSingleton()

or

UserActivity.Singleton.

but eclipse's code completion doesn't find anything

thanks!

ufk
  • 30,912
  • 70
  • 235
  • 386

3 Answers3

52

The trick is to make the enum itself the singleton. Try this:

public enum UserActivity {
    INSTANCE;

    private DataSource _dataSource;
    private JdbcTemplate _jdbcTemplate;

    private UserActivity() {
        this._dataSource = MysqlDb.getInstance().getDataSource();
        this._jdbcTemplate = new JdbcTemplate(this._dataSource);
    }

    public void dostuff() {
     ...
    }
}

// use it as ...
UserActivity.INSTANCE.doStuff();
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
13

INSTANCE is a member of Singleton, not of UserActivity - so you'd need:

UserActivity.Singleton.INSTANCE.getSingleton();

However, you haven't actually made UserActivity a singleton - normally you'd make the type itself an enum, not embed an enum within the type...

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Hiya.. for some reason I'm still kind of lost. I never used enum for a singleton class before. mind showing a small example ? – ufk Nov 06 '11 at 14:38
1
public class UserActivity {

    private DataSource _dataSource;
    private JdbcTemplate _jdbcTemplate;

    private static enum Singleton { // private, why not
        INSTANCE;

        private static final UserActivity singleton = new UserActivity();

        public UserActivity getSingleton() {
            return singleton;
        }
    }

    private UserActivity() { // private !!(*)
        this._dataSource = MysqlDb.getInstance().getDataSource();
        this._jdbcTemplate = new JdbcTemplate(this._dataSource);
    }


    public static UserActivity getInstance() {
     return UserActivity.Singleton.INSTANCE.getSingleton();
    } 

    public void dostuff() {
     ...
    }
}

and call UserActivity.getInstance().doStuff();

You can't call the constructor (*) and you can only get an instance of your UserActivity() class via the INSTANCE in the private enum - which is guaranteed to be created once and only once

Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
  • @NimC : Oh come on - it is. ufk was using the Lazy Load singleton pattern of which you are a well known enemy (:P) and was trying to make it work - the accepted answer was just taking the enum on the top level simplifying things – Mr_and_Mrs_D Oct 14 '12 at 16:19
  • the enum will only be loaded on demand anyway (by the classloader), this has no advantage. – NimChimpsky Oct 14 '12 at 17:05
  • 2
    @NimChimpsky : yes but the question was about how to make _this_ dialect work - not the top level enum one. One might want to know how one can make one's code work - out of curiosity - even if there are simpler ways to do things. The discussion for the differences between those idioms belongs [here](http://stackoverflow.com/questions/12883051/enum-and-singletons-top-level-vs-nested-enum) and is not settled IMHO :) – Mr_and_Mrs_D Oct 14 '12 at 17:15