Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/372.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 创建给定类集合的类对象_Java_Generics_Reflection_Java Reflection - Fatal编程技术网

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());