Home > front end >  How to initialize a list of a class type received as a parameter?
How to initialize a list of a class type received as a parameter?

Time:02-05

I am a beginner in Java.

How do I initialize a list of a class type received as a parameter? I have a method that takes in a Class<?> argument as a parameter, and I want to create a list of this class type.

public List<?> returnList(Class<?> listItemType) {
    //create a list of type "listItemType"
    //populate the list
    //return the list
}

I have tried doing

List<listItemType> list = new ArrayList<listItemType>()

but VSCode shows listItemType cannot be resolved to a type.

I have also tried <? extends listItemType>, <listItemType.getName()> and the below code, but they don't seem to work either.

Object obj = listItemType.getDeclaredConstructor().newInstance();
List<obj.getClass()> = new ArrayList<obj.getClass()>();

CodePudding user response:

If you make the method a generic method with a named type parameter it will work. For example:

public <T> List<T> returnList(Class<T> listItemType) {
    List<T> list = new ArrayList<>();
    try {
        list.add(listItemType.getConstructor().newInstance());
    } catch (ReflectiveOperationException ex) {
        // do something
    }
    return list;
}

Note that various exceptions are possible. For example, the class may not have a suitable constructor, constructor may not be accessible, or it may throw exceptions. A complete version of this method should do something appropriate, or declare the relevant exceptions so that they can propagate to the caller and beyond.

Without the named type parameter T you don't connect the wildcard in List<?> to the wildcard in Class<?>. So the compiler wouldn't know that returnList(Foobar.class) is intended to return a List<Foobar>.

And there is no way that you can use the variable name listItemType as a class name as in List<listItemType>. That's why you were getting "listItemType cannot be resolved to a type". Variable names and type names are in different Java namespaces.

Your attempt <? extends listItemType> fails for the same reason, and <listItemType.getName()> fails because an expression is not a type.

Another way to think about those failed attempts is that they use runtime values (e.g. the value of listItemType) to do compile time type checking. That implies that the compiler needs to be able to look into the future to see what the runtime values are going to be. Clairvoyance is not a feature of current generation Java compilers :-).

CodePudding user response:

What you need is a generic method.

Generic methods allow type parameters to be used to express dependencies among the types of one or more arguments to a method and/or its return type.

This is a full example:

public class NewMain {

    private static class Foo {

        public Foo() {
        }
    }
    
    public static void main(String[] args) {
        // TODO code application logic here
        List<Foo> foos = returnList(Foo.class);
        System.out.println(foos.get(0));
    }
    
    public static <T> List<T> returnList(Class<T> listItemType) {
        List<T> list = new ArrayList<>();
        try {
            T obj = listItemType.getConstructor().newInstance();
            list.add(obj);
        } catch (Exception ex) {
            Logger.getLogger(NewMain.class.getName()).log(Level.SEVERE, null, ex);
        }
        return list;
    }
    
}
  •  Tags:  
  • Related