9

I need to write a java method which takes a class (not an object) and then creates an ArrayList with that class as the element of each member in the array. Pseudo-code example:

public void insertData(String className, String fileName) {
      ArrayList<className> newList = new ArrayList<className>();
}

How can I accomplish this in Java?

2
  • 4
    Does it have to be String className? It'd be easier if you could pass the actual Class object in, like insertData(ExampleClass.class, fileName). Commented Feb 6, 2017 at 14:10
  • I do not know which class I am passing in. Commented Feb 7, 2017 at 15:09

4 Answers 4

5

You can use Generic methods

public <T> void insertData(Class<T> clazz, String fileName) {
   List<T> newList = new ArrayList<>();
}

but if you should use this contract insertData(String className, String fileName), you cannot use generics because type of list item cannot be resolved in compile-time by Java.

In this case you can don't use generics at all and use reflection to check type before you put it into list:

public void insertData(String className, String fileName) {
    List newList = new ArrayList();

    Class clazz;
    try {
        clazz = Class.forName(className);
    } catch (ClassNotFoundException e) {
        throw new RuntimeException(e); // provide proper handling of ClassNotFoundException 
    }

    Object a1 = getSomeObjectFromSomewhere();

    if (clazz.isInstance(a1)) {
        newList.add(a1);
    }
    // some additional code
}

but without information of class you're able use just Object because you cannot cast your object to UnknownClass in your code.

Sign up to request clarification or add additional context in comments.

5 Comments

Note that this changes the OP's method signature, which may or may not be desirable.
@VladBochenin Can you please provide an implementation example of the above code?
@Greymarch are you talking about using reflection and type cast in runtime?
@VladBochenin I dont know what technique to use, whether its reflection or something else. I just know I need to pass a class into a method, fill an ArrayList of that class with data, and the class is not known until runtime.
@Greymarch maybe I will able to help you more, if will know more context of this tasks. How are you going to create instances of unknown class? Why do you have this restrictions?
2

My guess is that what you really want to do is to return the generated List. This is what that might look like:

public <T> List<T> loadData(Class<T> clazz, String fileName) {
    List<T> newList = new ArrayList<>();

    //...populate list somehow (e.g. with values deserialized from the file named "filename")

    return newList;
}

This is how it could be used:

List<String> names = loadData(String.class, "someFileContainingNameStrings");
List<Double> temperatures = loadData(Double.class, "someFileContainingTemperatureData");

Comments

1

Vlad Bochenin gives a good way but it makes no sense to provide a T generic that derives from nothing in your method.
It puts zero constraints in the code of insertData() that manipulates the list.
You will be forced to do cast in the code and it defeats the purpose of Generics.

I suppose you want manipulate some instances of known classes in insertData().
And if you use generic in your case, it would have more meaningful if you have subtypes of classes to manipulate.

In this way, you could have a method that accepts a base type and its subclases.

public static <T extends YourClass> void insertData(Class<T> clazz, String fileName) {
    List<T> newList = new ArrayList<>();
    T t = newList.get(0);
    // here I can manipulate something that derives from YourClass
}

3 Comments

@Downvoter Could you explain ? As usually I suppose that no.
I'm not the downvoter, but your assertion that " it makes no sense to provide a T generic that derives from nothing in your method" is wrong. Sure, you can't call any methods on the items in the list from within the method unless you resort to reflection, but you can populate a List<T> (perhaps with values deserialized from the file with the given name). Usually you would want to return that list, though. At the callsite, you know T at compile time and can call any methods you like.
@Hulk In the question it doesn't return list. If it do, indeed, it would make sense. "you can populate a List<T> (perhaps with values deserialized from the file with the given name)." It defeats still the purpose of generics as you will put instances of something retrieved from a file in a List of Object. T derives from nothing, consequently only of Object. What is the advantage of Generics here ? In this case, we could simplify the API to remove the class parameter and add @SuppressWarnings in the insertData() method, as finally the Generics brings no safety here.
0

It is not a good practice, just an example of using Object and

this.array_employee = loadDataArrayListFromFileJson(fileName_employee, Employee.class);
this.array_movie = loadDataArrayListFromFileJson(fileName_movie, Movie.class);
this.array_store = loadDataArrayListFromFileJson(fileName_store, Store.class);
private <T> ArrayList<T> loadDataArrayListFromFileJson(String filename, Class class__) {
    ArrayList<T> arraylist_objects = new ArrayList<>();

    String jsonArrayString = getResourceAsString(filename);
    JsonParser parser = new JsonParser();
    Gson gson = new Gson();

    JSONArray json_array = new JSONArray(jsonArrayString);
    for (Object object : json_array) {
        JsonElement json_element = parser.parse(object.toString());
        Object element = gson.fromJson(json_element, class__);
        System.out.println(element);
        arraylist_objects.add((T) element);
    }
    return arraylist_objects;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.