문제

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