I would like to be able to create a new instance of the ? parametrized type but I can't find a way to do it.

import java.util.List;
import java.util.Map;
import java.util.Set;


class Pinput {
    public static void parse (String[] args, List<String> params, Map<String, ? extends List<String>> options, Set<String> flags, Set<String> flagSet){

        String optionalParameterKey;
        Boolean isOptionalParameter = false;

        for(int n = 0; n < args.length; ++n){
            String p = args[n];
            if (p.charAt(0) == '-'){
                isOptionalParameter = false;
                if(p.length() > 1){
                    if(p.charAt(1) == '-' || p.length() == 2){

                        if(flagSet.contains(p)){
                            flags.add(p);
                        }
                        else{
                            options.put(p, ?.newInstance());
                            optionalParameterKey = p;
                            isOptionalParameter = true;
                        }
                    }
                    else{
                        for(int i = 1; i < p.length(); ++i){
                            flags.add("" + '-' + p.charAt(i));
                        }
                    }
                }
            }
            else if(isOptionalParameter){
                options.get(optionalParameterKey).add(p);
            }
            else{
                params.add(p);
            }
        }
    }
}

Any idea?

有帮助吗?

解决方案

Simply put: You can't do that.

You can only instantiate an Object reflectively if you have the .class object for it, or an instance of the class you can retrieve it from. However, if you change your method signature as follows:

public static <T extends List<String>> void parse(String[] args, List<String> params, Map<String, T> options, Set<String> flags, Set<String> flagSet, Class<T> klass)  throws InstantiationException, IllegalAccessException

Then when you call it add MyStringList.class (or whatever the map value type is), you can change your constructor line to:

options.put(p,  klass.newInstance());

And your code should work as expected.

Edit:

I get this => Test.java:19: illegal start of expression Pinput.parse(args, params, options, flags, flagSet, ArrayList<String>.class);

ArrayList<String> does not extend List<String>, ArrayList<T> extends List<T> and String extends Object which means it's valid as T. This would only work with a class declared as:

class MyStringList extends List<String>

Generics are not really appropriate for what you are trying to do, really you should just use this as your signature:

public static void parse(String[] args, List<String> params, Map<String, List<String>> options, Set<String> flags, Set<String> flagSet)

And manually instantiate the list as an ArrayList:

 options.put(arg,  new ArrayList<String>());

As List is only an interface, the compiler knows that you will provide some implementation of that interface, and then only allow you access to the List methods.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top