Java 创建给定类集合的类对象
是否可以人工创建一个Java 创建给定类集合的类对象,java,generics,reflection,java-reflection,Java,Generics,Reflection,Java Reflection,是否可以人工创建一个参数化类型对象,作为特定指定类型集合的定义?如果我有一个命名的集合字段,我可以有一个正确的定义,例如,对于这样一个类中的字段 public class MyContainerClass { List<String> myElementsList; } 但是我不知道如何仅通过反射创建这样一个参数化类型 换句话说,我需要一个通用的解决方案,以便通过以下测试代码: Class<?> elementClass = MyElement.class; Pa
参数化类型
对象,作为特定指定类型集合的定义?如果我有一个命名的集合字段,我可以有一个正确的定义,例如,对于这样一个类中的字段
public class MyContainerClass {
List<String> myElementsList;
}
但是我不知道如何仅通过反射创建这样一个参数化类型
换句话说,我需要一个通用的解决方案,以便通过以下测试代码:
Class<?> elementClass = MyElement.class;
ParameterizedType parameterizedType = implementMe(elementClass, List.class);
Assertions.assertEquals(List.class.getName(), parameterizedType.getRawType().getTypeName());
Assertions.assertEquals(elementClass.getName(), ((Class<?>)pt.getActualTypeArguments()[0]).getName());
Class elementClass=MyElement.Class;
ParameteredType ParameteredType=implementMe(elementClass,List.class);
assertEquals(List.class.getName(),parameterizedType.getRawType().getTypeName());
assertEquals(elementClass.getName(),((类)pt.getActualTypeArguments()[0]).getName());
你的问题毫无意义。我想你需要的是一本关于泛型是什么的入门书
它们是编译器检查的注释
就这些。编译器将使用它们生成警告、错误和静默强制转换。然后编译器将抛出该信息。一个例外是泛型出现在可能影响其他源文件中代码编译的类型中,因此签名中出现的任何类型(字段的类型、任何扩展的子句、任何方法参数的类型或任何方法的返回类型)-但这是由编译器通过在类文件中“作为注释”写入此信息来处理的-JVM本身完全忽略所有这些内容。一点也不在乎
您的建议意味着,在编译时,您无能为力;它是动态的
但是泛型只在编译时存在
因此,你想要的,将是完全无用的。因此,你的问题的实际答案(即:你想要什么是完全不可能的)实际上不是问题。因为想这样做没有意义
还有几个问题:
containerClass.getGenericSuperclass();
这和你想象的不一样。java.lang.Class
变量不能保存泛型。你自己试试看:
List<String> list1 = new ArrayList<String>();
List<Integer> list2 = new ArrayList<Integer>();
sysout(list1.getClass() == list2.getClass();
然后,唯一的方法是使用ASM、BCEL或其他字节码创建工具在运行时创建一个全新的类,并通过类装入器的defineClass将其装入,从而永久性地消耗进程的内存。这绝对没有什么用处,所以我很怀疑你会想这么做。它也相当复杂。这里是implementMe
public class TypeImpl implements Type {
private final Class<?> clazz;
public TypeImpl(Class<?> clazz) {
this.clazz = clazz;
}
@Override
public String getTypeName() {
return clazz.getName();
}
}
public ParameterizedType implementMe(Class<?> elementClass, Class<?> collectionClass) {
return new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
return new Type[] {
new TypeImpl(elementClass)
};
}
@Override
public Type getRawType() {
return new TypeImpl(collectionClass);
}
@Override
public Type getOwnerType() {
return null;
}
};
}
另外,请注意,对于两种类型的List
和List
类型不同,但类别相同List
。那么你已经有了collectionClass
恐怕你错了。虽然在您的示例中,对于简单变量,这些信息会丢失,但在运行时可以从类中获取有关其字段的geberics信息,并且这些字段包含任何基于泛型的类中的类的信息。请随便问这样的问题,我很乐意提供代码。同时,我将试图澄清这个问题。我实际上在问题中加入了工作代码,看一看。@Dariusz-“在运行时可以从类中获取有关其字段的泛型信息”,我在回答中明确提到了这一点。请完整阅读并理解它,然后再加上“这是错误的”。@Dariusz和你的编辑不会改变我的答案是你所期待的。特别是关于:不能反射创建新类实例的部分。完全你可以定义全新的类,用BCEL、ASM或诸如此类的工具动态生成它们,而你肯定不想这样做。我编辑了我的问题。我不需要创建类
,我只需要参数化类型
。对此我很抱歉。请删除类创建部分,因为它们实际上是离题的-再一次,我的错。我希望人们能够以某种方式使用现有的参数化类型的实现,但显然不是这样。
List<String> list1 = new ArrayList<String>();
List<Integer> list2 = new ArrayList<Integer>();
sysout(list1.getClass() == list2.getClass();
public <T> List<T> makeListOf(T type) {
// .. stuff here
}
such that:
List<String> list = makeListOf(String.class);
assertEquals(list.getClass()
.getGenericSuperclass().toString(),
"AbstractList<String>");
public class TypeImpl implements Type {
private final Class<?> clazz;
public TypeImpl(Class<?> clazz) {
this.clazz = clazz;
}
@Override
public String getTypeName() {
return clazz.getName();
}
}
public ParameterizedType implementMe(Class<?> elementClass, Class<?> collectionClass) {
return new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
return new Type[] {
new TypeImpl(elementClass)
};
}
@Override
public Type getRawType() {
return new TypeImpl(collectionClass);
}
@Override
public Type getOwnerType() {
return null;
}
};
}
Class<?> elementClass = String.class;
ParameterizedType parameterizedType = implementMe(elementClass, List.class);
System.out.println(List.class.getName().equals(parameterizedType.getRawType().getTypeName()));//true
System.out.println(elementClass.getName().equals(((Class<?>)pt.getActualTypeArguments()[0]).getName()));//true
Class<Class<?>> classClass = (Class<Class<?>>) (Object) Class.class;
Constructor<Class<?>> constructor = classClass.getDeclaredConstructor(ClassLoader.class);
constructor.setAccessible(true);//java.lang.SecurityException: Cannot make a java.lang.Class constructor accessible
Class<?> newClass = constructor.newInstance(this.getClass().getClassLoader());