4

How do you instantiate a Java generics Object that takes type parameters given only a Class or Class<?> object?

For example: Normally one can instantiate an ArrayList of Integer objects using the following syntax:

ArrayList<Integer> foo = new ArrayList<Integer>();

However, given a Class<?> object such as Integer.class, how could one create a similar ArrayList? For example, how would I do something like this (incorrect syntax):

ArrayList<Integer.class> foo = new ArrayList<Integer.class>();

I need this for something very unusual I am doing with Java (Creating an open-source tool for visualizing user-supplied instances of data structure/ generic classes they write). Here is an example of how I would be using this code which illustrates the information I would be given:

import java.util.ArrayList;
import java.util.List;

public class ArrayListFromClass {
    // obviously this code does not work
    public static void main(String[] args) {
        Object givenObject = new Integer(4);
        // I would not know it is Integer.class, a Class<?> object would be supplied by the user/ as a generic
        Class<?> cls = givenObject.getClass();
        List<cls> bar = new ArrayList<cls>();

        // Where args[0] is "Integer.class"
        List<args[0]> foo = new ArrayList<args[0]>();

        // then I would be able to add to foo or bar with one or both of these techniques:
        // printing givenObject.getClass() gives you java.lang.Integer, don't worry about the casting not working.
        bar.add(cls.cast(givenObject));
        Integer y = 6;
        bar.add(y);
    }
}
BlueOxile
  • 301
  • 2
  • 11
  • If you down vote, please let me know how I can write better/ more constructive posts in the future, or how I can edit this one. I am fairly knew at SO. – BlueOxile Jul 26 '17 at 23:09
  • This is not a place you can use Java generics (a compile time type checking mechanism). Since you want to be able to store any type, just use `Object`. And then you'll also need to use *reflection* when you iterate to appropriately handle individual instances. – Elliott Frisch Jul 26 '17 at 23:09
  • The post was downvoted because this has been asked tons of times before and you've shown no evidence of prior research. I'm actually surprised it's upvoted. – Sotirios Delimanolis Jul 26 '17 at 23:18

2 Answers2

1

Java is statically typed. The reason you would want to instantiate an ArrayList like so:

ArrayList<Integer> foo = new ArrayList<>();

is to let your IDE/compiler know that whenever something other than Integer is put into the list, show an error. Other than that the internals will ignore this initialization, in fact even erase the type.

So when you get your Class<?> object at runtime, you only know the type of the class when your code actually runs. So the IDE/Compiler wouldn't be able to warn you before runtime whether there is something wrong in your code.

So a List<Object> will do just fine in your case. If you want type safety you will have to check on your own like so:

    String sampleString = "String";
    Class<?> clazz = sampleString.getClass();
    ...
    if (clazz.isInstance(sampleString)) {
        list.add(sampleString);
    }

.isInstance(Object obj) is the equivalent of instanceof when you actually have a Class<?> at hand.

A1m
  • 1,579
  • 1
  • 14
  • 33
0

You don't need to worry about the generic parameter. Turns out that generic parameters are actually erased at runtime (see type erasure).

So you will just need to make it List<Object>.

This may seem like a problem, but it rarely matters. You will just need to keep track of the type that you put in and make sure that you remove and cast properly. Most of the time when using reflection the concrete types of your Objects don't really matter since you invoke methods, and access fields indirectly.

Neil Locketz
  • 3,736
  • 1
  • 22
  • 33