In order for you to be able to instantiate any element of type T
in this situation you will need to use reflection and also some conditions have to be met:
you can only get the type of T
if the array is not null and there is at least one element in the array. Due to type erasure there is no direct way of inferring the type without the presence of an actual object in the array.
then you have to check if the constructor of the first object in the array has a no args argument.
Here is a executable example below which you can try out:
import javax.swing.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class TypeClass<T> {
public TypeClass(T[] array) throws IllegalAccessException, InvocationTargetException, InstantiationException {
if(array != null && array.length > 0) { // You can only get the type of T if the arrays is not null and there is at least one element in the array
T first = array[0];
Class<?> clazz = first.getClass();
Constructor<?>[] constructors = clazz.getConstructors();
for(Constructor<?> constructor : constructors) {
int parameterCount = constructor.getParameterCount(); // Check if the constructor has a no args argument
if(parameterCount == 0) {
T o = (T) constructor.newInstance();
// Do something with the new object
System.out.println(o);
}
}
}
}
public static void main(String[] args) throws IllegalAccessException, InstantiationException, InvocationTargetException {
JFrame[] jframes = new JFrame[]{new JFrame()};
TypeClass<JFrame> typeClass = new TypeClass<>(jframes);
}
}
If you run this you will see something like this om the console:
javax.swing.JFrame[frame0,0,0,0x0,invalid,hidden,layout=java.awt.BorderLayout,title=,resizable,normal,defaultCloseOperation=HIDE_ON_CLOSE,rootPane=javax.swing.JRootPane[,0,0,0x0,invalid,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777673,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]
Update
You could also specify an alternative constructor which indicates specifically the type to instantiate via reflection. This makes more sense, because the type of elements in the array might actually subclass type T
. Here is an example of an alternative constructor:
// Alternative with the specific type for instantiation
public TypeClass(T[] array, Class<T> tClass) throws IllegalAccessException, InvocationTargetException, InstantiationException {
if(tClass != null) {
Class<?> clazz = tClass.getClass();
Constructor<?>[] constructors = clazz.getConstructors();
for(Constructor<?> constructor : constructors) {
int parameterCount = constructor.getParameterCount(); // Check if the constructor has a no args argument
if(parameterCount == 0) {
T o = (T) constructor.newInstance();
// Do something with the new object
System.out.println(o);
}
}
}
}