只有Collection子接口,List、Set这样的接口的Class字节码时,怎么生成他对应的子类。

前置条件:最近在写框架工具,现拿到了一个类的class,遍历他的属性时,遇到Collection的子接口问题时,无法确定类中的属性是一个List还是set 或者Queue ,只能确定属性是Collection的子接口。但是需要遍历这个属性的同时,假如他是集合类,则需要调用其add方法,所以需要拿到这个属性的实例子类。

需求例子:比如我通过反射获得了一个类的属性:

private List<String> list

有了list的字节码class,现在需要创建他的某个子类实例对象并且调用其中的方法。
因为是list是接口,所以不能通过class创建其实例

此贴终结, 方案: 取class分类讨论。

                                    //属性
                                    Object instance = tempC.newInstance();
                                    //迭代解析
                                    resoleParam(instance,instance.getClass());
                                    Collection collection = null;
                                    //如果是list 这样的接口或抽象类
                                    if(aClass.isInterface()|| Modifier.isAbstract(aClass.getModifiers())){
                                        //实例化它的可用类
                                       collection = getNewInstanceWhenCollection(aClass);
                                    }else{
                                        //如果是可实例子类,则直接调用
                                        collection = (Collection)aClass.newInstance();
                                    }

                                    collection.add(instance);
                                    field.set(obj,collection);
    /**
     * 当class为collection 子接口或抽象类时,分类讨论 取出适合class的子类实例
     * @param clazz
     * @return
     */
    private Collection getNewInstanceWhenCollection(Class clazz){
        //判断是否是集合
        if(!Collection.class.isAssignableFrom(clazz)){
            return null;
        }

        //判断是list分支吗
        if(List.class.isAssignableFrom(clazz)){
            return new ArrayList();
        }

        //判断是set分支吗
        if(Set.class.isAssignableFrom(clazz)){
            return new HashSet();
        }

        //判断是队列分支吗
        if(Queue.class.isAssignableFrom(clazz)){
            return new LinkedList();
        }
        return null;
    }

都使用反射了,那创建实例就是你说了算,List的子类你任意创建一个,再赋值给list属性就行了。

直接 set 实现类即可,示例代码如下:

public class Test {

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Bean bean = new Bean();
        Class<? extends Bean> cls = bean.getClass();
        Field list = cls.getDeclaredField("list");
        if (Collection.class.isAssignableFrom(list.getType())) {
            list.setAccessible(true);
            list.set(bean, new ArrayList<>());
        }
    }

}


        T obj = beanClass.newInstance();
        Class<?> oo = obj.getClass();
        List<Class<?>> clazzs = new ArrayList<>();
        while (true) {
            clazzs.add(oo);
            oo = oo.getSuperclass();
            if (oo == null || oo == Object.class) {
                break;
            }
        }