Initialize Java parameter / generic type using Class object
How do you create a Java generics Object instance that takes type parameters given only to the object Class
or Class<?>
?
For example: You can usually create an instance of ArrayList
objects Integer
using the following syntax:
ArrayList<Integer> foo = new ArrayList<Integer>();
However, given an object Class<?>
, for example Integer.class
, how can one create a similar one ArrayList
? For example, how would I do something like this (wrong syntax):
ArrayList<Integer.class> foo = new ArrayList<Integer.class>();
I need this for something very fancy, which I am doing with Java (making an open source tool to render user-provided instances of the data structure / generic classes they write). Here is an example of how I will use this code, which illustrates the information that will be given to me:
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);
}
}
source to share
Java is statically typed. The reason why you would like to instantiate ArrayList like so:
ArrayList<Integer> foo = new ArrayList<>();
means your IDE / compiler knows that whenever anything other than is placed in the list Integer
, an error message is thrown. In addition, the internals will ignore this initialization, in fact, even erase the type .
So when you get your object Class<?>
at runtime, you only know the type of the class when your code actually works. This way, the IDE / Compiler will not be able to warn you before starting if there is something wrong with your code.
This way List<Object>
will work great in your case. If you want type safety you will need to check for yourself:
String sampleString = "String";
Class<?> clazz = sampleString.getClass();
...
if (clazz.isInstance(sampleString)) {
list.add(sampleString);
}
.isInstance(Object obj)
is the equivalent instanceof
when you actually have Class<?>
.
source to share
You don't need to worry about the general parameter. It turns out that shared parameters are actually erased at runtime (see type of erasure ).
Therefore, you just have to do it List<Object>
.
This may sound like a problem, but it rarely matters. You just need to keep track of the type you entered and make sure you remove and drop correctly. Most of the time when you are using reflection, the specific types of yours Object
don't really matter as you call methods and touch the fields indirectly.
source to share