当前位置: 首页 > 知识库问答 >
问题:

创建给定类的集合的类对象

公羊伟志
2023-03-14

是否可以人为地创建一个Parameter izedType对象,它将是特定指定类型的集合的定义?如果我有一个命名的集合字段,我可以有正确的定义,即。像这样的类中的字段

public class MyContainerClass {
  List<String> myElementsList;
}

我可以通过以下代码提取我需要的所有信息。

public class GetGenericsTest {
    public static class MyContainerClass {
        List<String> myElementsList;
    }

    public static void main(String[] args) throws Exception {
        Field field = MyContainerClass.class.getDeclaredField("myElementsList");

        ParameterizedType pt = (ParameterizedType) field.getGenericType();
        System.out.println("collection type: " + pt.getRawType().getTypeName());
        System.out.println("elt type:        " + ((Class<?>)pt.getActualTypeArguments()[0]).getName());
    }
}

这产生:

collection type: java.util.List
elt type:        java.lang.String

但是我不知道如何仅通过反射创建这样的<code>ParameterizedType</code>。

换句话说,我需要一个通用的解决方案,以便通过以下测试代码:

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

共有2个答案

那绪
2023-03-14

你的问题没有意义。我认为你需要的是一个关于泛型是什么的简短入门。

它们是经过编译器检查的注释。

这就是他们的全部。编译器将使用它们生成警告、错误和静默强制转换。然后编译器将抛出该信息。一个例外是泛型出现在可能影响其他源文件中代码编译的类型中,因此,出现在签名中的任何类型(字段的类型、任何<code>扩展的</code>子句、任何方法参数的类型或任何方法的返回类型)-但这是由编译器通过在类文件中写入该信息来处理的,“作为注释”-JVM本身完全忽略了所有这些内容。一点也不在乎。

您的建议意味着,在编译时,您无能为力;它是动态的。

但是泛型只存在于编译时。

因此,你想要的,是完全没用的。因此,你的问题的实际答案(即:你想要的完全不可能) - 实际上不是问题。因为想要这样做是没有意义的。

几个进一步的问题:

containerClass.getGenericSuperclass();

这不是你想的那样。< code>java.lang.Class变量不能保存泛型。亲自尝试一下:

List<String> list1 = new ArrayList<String>();
List<Integer> list2 = new ArrayList<Integer>();
sysout(list1.getClass() == list2.getClass();

上面打印出“true”,从而证明泛型部分不在类变量中。另外,< code >类

. getDynamicSuperclass()为您提供的是AbstractList

公共类Myclass扩展AbstractList

注意,如果你在ArrayList上尝试这个技巧,你会得到<code>ArrayList中的真正含义。javaAbstractList

如果你想让这个方法奏效:

public <T> List<T> makeListOf(T type) {
    // .. stuff here
}

such that:

List<String> list = makeListOf(String.class);
assertEquals(list.getClass()
   .getGenericSuperclass().toString(), 
   "AbstractList<String>");

那么唯一的方法就是使用ASM或BCEL或其他字节码创建工具在运行时创建一个全新的类,并通过类加载器的定义类加载它,永久占用进程的内存。这绝对没有任何有用的目的,所以我非常怀疑你会想这么做。这也很复杂。

车思淼
2023-03-14

这里是实现我

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

但是我想不出如何仅通过反射来创建这样的< code >类。

您无法创建自己的。这是一个最终类,具有私有构造函数。

的Javadoc说

类没有公共构造函数。相反,类对象由 Java 虚拟机在装入类时自动构造,并通过调用类装入器中的 defineClass 方法自动构造。

如何扩展最终类?(反射、Jav辅助)

如何在Java中扩展最终类

是否可以在Java中扩展最终类?

如果您尝试通过反射克服class构造函数的私有访问,您将拥有SecurityExc的

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

另外请注意,对于两种类型的<代码>列表

 类似资料:
  • 我想使用流从类型B创建类型a的集合。 假设我有两节课 为了从员工集合中创建人员集合,我编写了以下代码 目前,这段代码可以正常工作。但我想知道,是否有更好的方法可以不使用forEach从员工创建人员集合。

  • 主要内容:类的定义,创建对象,访问类的成员,使用对象指针,总结类和对象是 C++ 的重要特性,它们使得 C++ 成为面向对象的编程语言,可以用来开发中大型项目,本节重点讲解类和对象的语法,如果你对它们的概念还不了解,请先阅读《 C++类和对象到底是什么意思》。 类是创建对象的模板,一个类可以创建多个对象,每个对象都是类类型的一个变量;创建对象的过程也叫类的实例化。每个对象都是类的一个具体 实例(Instance),拥有类的成员变量和成员函数。 有些教程将类的

  • 公共类DoSomething{private static final Logger Logger=LoggerFactory.getLogger(DoSomething.class); 我试图创建一个LogMessage的对象。并在DoSomething类的方法中使用它。这是好的还是我应该移动方法中的行?

  • 使用Python3的函数注释,可以指定同构列表(或其他集合)中包含的项的类型,以便在PyCharm和其他IDE中进行类型暗示? int列表的伪python代码示例: 我知道使用Docstring是可能的... ... 但如果可能的话,我更喜欢注释样式。

  • 问题内容: Jackson JSON序列化/反序列化此类没有问题: 但是在这一点上: 反序列化时出现此异常: com.fasterxml.jackson.databind.JsonMappingException:没有为类型[简单类型,类test.MyClass $ Nested]找到合适的构造函数:无法从JSON对象实例化(缺少默认构造函数或创建者,或者可能需要添加/启用类型信息?),网址为[S

  • 我在弄清楚如何根据给定的类型在构造函数中创建一个新对象时遇到了困难。 例如,我有一个机器人驱动程序,它有一个默认构造函数,不接受任何参数,并创建一个基本的机器人。但我有另一个构造器,根据这个论点创造了一个新的机器人。 是一个接口。那么,如果我想创建,使其是另一种类型,比如?我需要做一些类型的铸造吗?