Search code examples
javainria-spoon

Map from int to class


I want to create objects of different classes based on user input, i.e. the user will tell which class's object to create. I have something like this :

launcher.addProcessor((Processor) new SerializableFieldProcessor(projectKey));

Now I have other processors and want the user to give an integer input and depending on that, the respective processor's object to be created. A straightforward way is to use switch cases, but later on I'm going to have more than 50 or 100 separate processors. Is there a way to do this with a map or something similar? Something like this :

Map<int,Processor> mymap;
//initialize mymap;
int x= user_input;
launcher.addProcessor((Processor) new mymap[x]);

Solution

  • Another solution you might want to consider is as follows:

    Map<Integer, Class<? extends Processor>> map = new HashMap<>();
    // Integer.valueOf(x) used to prevent autoboxin just a matter of opinion.
    map.put( Integer.valueOf( 0 ), MyProcessor.class );
    
    Processor chosen = map.get( userIn ).getConstructor( String.class ).newInstance( projectKey );
    
    launcher.addProcessor(chosen);
    

    It is basically the same but the difference is that the returned object is of the type Processor and the class does definitly exist. When you are using a String and Class.forName(...) there are two additional exceptions that may be thrown. First the ClassNotFoundException which will be thrown if the Class.forName() method did not find the class for the given name. The 2nd additional exception is the ClassCastException which will be thrown if the created object is not an implementation or subclass of Processor.


    Explanation:

    We are using a map with an Integer as our key and a Class<? extends Processor> as our value. A Class<T> object can be considered as an object representation of the corresponding .class file (technically incorrect but for the sake of simplicity we assume it is that way). What does <? extends Processor> mean in concrete? It means that the map will only allow values of Classes which are an implementation or a subtype of Processor. Doing so eliminates the thread of a ClassCastException because if we can only store classes which extend Processor we can only retrieve classes which can be casted to an Processor without any issues or even the thread of one.


    Note: I chained the instantiation process which usually is a bad idea in a productive environment but it shortens the code quite a lot and there is no need to further explain it since you use the exact same approach in your own answer.