Initialize a new object from class in Enum

前端 未结 8 551
轻奢々
轻奢々 2021-01-03 00:27

I have an Enum called Plugins:

public enum Plugins {

    ROTATING_LINE (plugin.rotatingline.RotatingLine.class),
    SNOW_SYSTEM (plugin.snow.SnowSystem.cla         


        
8条回答
  •  挽巷
    挽巷 (楼主)
    2021-01-03 01:05

    Enums in this situtation will make your life more difficult.

    In the past I've solved this problem this way:

    class PluginFactory {
    
            private Class clazz;
    
            PluginFactory(Class clazz) {
                this.clazz = clazz;
            }
    
            T newInstance() {
                return clazz.newInstance();
            }
    
        final static PluginFactory SNOW_SYSTEM_FACTORY = 
                new PluginFactory(SnowSystem.class);
        ...
    
        // should really use a list and a wilcard generic bounded by Plugin, but it's
        // too verbose for me for the purposes of this answer
        final static PluginFactory[] FACTORIES = {SNOW_SYSTEM_FACTORY, ...};
    
        public static void main(String[] args) {
            Plugin[] arr = new Plugin[FACTORIES.length];
            for (int i = 0; i < arr.length; i++) {
                arr[i] = FACTORIES[i].newInstance();
            }
    
            // more usefully though
            SnowSystem ss = SNOW_SYSTEM_FACTORY.newInstance();
            ss.setValue(123);
        }
    
    }
    

    The other option is to give newInstance var args object parameter. Then use reflections to find the appropriate constructor that takes these types as parameters. This is hideously messy and completely unsafe if a user of the API gives a bad set of arguments (exception thrown).

    public T newInstance(Object... args) {    
        for (Constructor c : clazz.getConstructors()) {
            if (isMatchingConstructor(c, args)) {
                return clazz.cast(c.newInstance(args));
            }
        }
        throw new NoSuchMethodException("No matching constructor found for args: " 
                + Arrays.toString(args));
    }
    
    private boolean isMatchingConstructor(Constructor c, Object... args) {
        Class[] parameters = c.getParameterTypes();
    
        if (parameters.length != args.length) {
            return false;
        }
    
        for (int i = 0; i < args.length; i++) {
            if (!parameters[i].isAssignableFrom(args[i].getClass())) {
                return false;
            }
        }
        return true;
    }
    

提交回复
热议问题