Using Java Enums to Return Collections of Other Enums

Posted by Tejus Parikh on February 25, 2010

I really like Java enums as a way to organize and consolidate all the string constants that come with building systems with a lot of settings files. In our case in particular, we have an ETL process that moves data between sources that have no knowledge of each other. All checks to ensure that there are only valid values in each system need to happen in the Java code. Enums are perfect for this, but some of our settings are hierarchical and it’s a little unclear how this would work in code. Our lexicon looks a little like this:


music

 \

    jazz

    pop

    funk

    blues

    rock

|

article

 \

    blog

    feature

    review

|

video

 \

    music

    interview

    comedy

Creating an enum for the top level is straight-forward:

public enum Scheme {

	music, article, video;

}

So now how do we get Scheme.music to return the valid values for it’s subtypes? First we need to create a marker interface:

public interface SchemeClass {}

You can add abstract methods on an enum, so we can create a method that will return an array of SchemeClasses:

public enum Scheme {

	music, article, video;

	

	abstract public SchemeClass[] getClasses();

}

And while we’re at it, lets create the enums for the sub-categories (consolidated here, but in practice I put them in different files):

public enum MusicClasses implments SchemeClasses {

    jazz, pop, funk, blues, rock;

}



public enum ArticlesClasses implements SchemeClasses {

    blog, feature, review;

}



public enum VideoClasses implements SchemeClasses {

    music, interview, comedy;

}

The important thing is that all of these enums implement the SchemeClass interface. Now to get the Scheme enums to return the list of valid subtypes. Now all that’s left is implementing the abstract method for each of the possible values in Scheme.

public enum Scheme {

    music {

        public SchemeClass[] getClasses() {

            return MusicClasses.values();

        }

    },

    article {

        public SchemeClass[] getClasses() {

            return ArticleClasses.values();

        }

    },

    video {

        public SchemeClass[] getClasses() {

            return VideoClasses.values();

        }

    }

    ;

    abstract public SchemeClass[] getClasses();

}

Tejus Parikh

I'm a software engineer that writes occasionally about building software, software culture, and tech adjacent hobbies. If you want to get in touch, send me an email at [my_first_name]@tejusparikh.com.