Java 如何从传递给函数的列表T[]中获取泛型T的类型,然后使用T进行实例化?
例如,假设有一个代码块,如下所示:Java 如何从传递给函数的列表T[]中获取泛型T的类型,然后使用T进行实例化?,java,Java,例如,假设有一个代码块,如下所示: public className<T> { public className(T[] varName) { //somecode } } 公共类名{ 公共类名(T[]varName){ //一些代码 } } 如何从T[]的实例中获取T的类型,然后使用它来实例化T类型的对象?为了使您能够实例化T类型的任何元素,在这种情况下,您需要使用反射,并且必须满足一些条件: 如果数组不为null且数组中至少有一个元素,则只能
public className<T> {
public className(T[] varName) {
//somecode
}
}
公共类名{
公共类名(T[]varName){
//一些代码
}
}
如何从T[]的实例中获取T的类型,然后使用它来实例化T类型的对象?为了使您能够实例化T类型的任何元素,在这种情况下,您需要使用反射,并且必须满足一些条件:
- 如果数组不为null且数组中至少有一个元素,则只能获取
的类型。由于类型擦除,在数组中不存在实际对象的情况下,无法直接推断类型T
- 然后,您必须检查数组中第一个对象的构造函数是否有no args参数
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);
}
}
更新
您还可以指定一个替代构造函数,该构造函数专门指示要通过反射实例化的类型。这更有意义,因为数组中的元素类型实际上可能是typeT
的子类。下面是一个替代构造函数的示例:
// 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);
}
}
}
}
//具有用于实例化的特定类型的备选方案
公共类型类(T[]数组,类tClass)抛出IllegaAccessException、InvocationTargetException、InstanceionException{
if(tClass!=null){
类clazz=tClass.getClass();
构造函数[]constructors=clazz.getConstructors();
for(构造函数:构造函数){
int parameterCount=constructor.getParameterCount();//检查构造函数是否有无args参数
如果(参数计数==0){
T o=(T)构造函数.newInstance();
//对新对象执行某些操作
系统输出打印ln(o);
}
}
}
}
恐怕您不能这样做。泛型在运行时被擦除,因此您的方法将获得一个对象[]
,而不是T[]
。您必须传递一个类对象,答案是cannot,但C#can do。你必须以param的身份通过这门课,我不确定这是不是该走的路。数组MyObject[]
可以包含MyObject
的子类元素。在我看来,仅使用第一个元素似乎相当随意。创建任意实例可能会产生不可预知的后果。@LuCio你是对的。可能存在子类。另一个更好的选择是使用classclazz
更改构造函数,并精确指定要实例化的类型。这肯定是一个比这个更好的解决方案。在新方法中,array
是未使用的,因此它实际上没有回答这个问题。如果只是“从T[]
的实例中获取T
的类型”,我们可以调用array.getClass().getComponentType()
。你也给出了一个答案,这可能是一个合适的答案。但是国际海事组织OP还没有澄清背景。因此,我的第一个评论需要OP来回答。但现在游戏结束了;)
// 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);
}
}
}
}