通过反射检查 Class<?> 是否是 other 的实例

Checking if a Class<?> is instane of other by reflection

我正在尝试创建任何 class 的随机生成器以进行压力测试。

我的生成器目标是使用默认构造函数创建任何 class 并填充其原始字段和字符串字段(通过反射)

我还想填写数字类型(整数、长整型、双精度....)的字段,因为它们很容易转换为基元。

但我找不到一种简单的方法 instanceof 类型之间。

方法在这里

public static <V> Collection<V> createMassiveCollection(Class<V> clazz, int amount, Class<?> collectionType) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {

        Random r = new Random();
        RandomGenerator rg = new RandomGenerator();
        @SuppressWarnings("unchecked")
        Collection<V> collection = (Collection<V>) collectionType.newInstance();
        for (int i = 0; i < amount; i++) {
            V item = clazz.newInstance();

            for (Field field : item.getClass().getDeclaredFields()) {

                if (java.lang.reflect.Modifier.isStatic(field.getModifiers()) || java.lang.reflect.Modifier.isFinal(field.getModifiers()))
                    continue;

                field.setAccessible(true);

                if (field.getType().equals(String.class))
                    field.set(item, rg.nextCompliment());

                else if (field.getType().isPrimitive() && (field.getType() != boolean.class && field.getType() != byte.class && field.getType() != char.class))
                    field.set(item, r.nextInt(1000000));

                else {
                    Constructor<?> c = null;

                    try {
                        c = field.getType().getConstructor(String.class);
                    }
                    catch (Exception e) {}
                    if (c != null && Number.class.isInstance(c.newInstance("1")))
                        field.set(item, field.getType().getConstructor(String.class).newInstance(r.nextInt(1000000) + ""));
                }

            }

            collection.add(item);
        }
        return collection;
    }

第三个 if 是导致问题的那个 我想要这样的东西:"if Type<C> is subtype of Type<V>" 但我发现的所有方法都需要一个有效的对象实例来检查。

例如。 Number.class.isInstance(field.getType())field.getType() instanceof Number 都不起作用,因为 field.getType() 是类型的实例。

有谁知道这是否可行?

我想在我的方法签名中提出另一个问题(不太重要)

Class<? extends Collection<V>> collectionType

但是如果我在尝试调用

之类的方法时这样做
createMassiveCollection(User.class, 100000, new ArrayList<User>().getClass());

编译失败!所以,为了能够编译,我必须相信用户正在传递某种扩展集合的类型作为参数

检查 Class#isAssignableFrom() 可以确定一个 class 是否是另一个的子类型。示例:

System.out.println(String.class.isAssignableFrom(Object.class));
System.out.println(Object.class.isAssignableFrom(String.class));

输出

false
true

要检查 class 是否是另一个的子 class,您必须使用 isAssignableFrom:

if (Number.class.isAssignableFrom(field.getType()) { // ...

对于你的第二个问题,你需要第二个通用的:

public static <V, C extends Collection<?>> Collection<V> createMassiveCollection(Class<V> clazz, int amount, Class<C> collectionType)

您也可以将此泛型定义为 C extends Collection<V>,但这会产生编译器警告并且不会阻止像 createMassiveCollection(String.class, 10, new ArrayList<Number>().getClass()).

这样的调用

顺便说一下,我的最后一个参数是 ArrayList.class

  1. field.getType() 做 return Class<?>type 属性 名称来自 Java 1,当时没有泛型,因此没有 Type 接口。乍一看可能会令人困惑。

  2. 要测试一个 Class<?> 代表的 class 是否是另一个 Class<?> 代表的 class 的子类型,你需要使用 classA.isAssignableFrom(classB)。例如Number.class.isAssignableFrom(Integer.class) 将 return 为真。

  3. Class<? extends Collection<V>> collectionType 是可能的,但毫无意义,因为如果没有明确的不安全转换,您将无法获得 Class<? extends Collection<V>> 的实例。因为

    1. Attempting to write class literals of generic types, except a wildcard type, will result in compile time errors.
    2. Object.getClass() 将 return 擦除类型。例如new ArrayList<User>().getClass() 的 return 值的类型将是 ArrayListArrayList<?>,它们的含义是相同的。

    没有明确的不安全转换,只有当 V 是通配符时才能调用此方法。