13

How To Instantiate a java.util.ArrayList with Generic Class Using Reflection? I am writing a method that sets java.util.List on target object. A target object and a generic type of list is knowing in runtime:

public static void initializeList(Object targetObject, PropertyDescriptor prop, String gtype) {
    try {
        Class clazz = Class.forName("java.util.ArrayList<"+gtype+">");
        Object newInstance = clazz.newInstance();
        prop.getWriteMethod().invoke(targetObject, newInstance);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

7 Answers 7

15

An object doesn't know about its generic type at execution time. Just create a new instance of the raw type (java.util.ArrayList). The target object won't know the difference (because there isn't any difference).

Basically Java generics is a compile-time trick, with metadata in the compiled classes but just casting at execution time. See the Java generics FAQ for more information.

Sign up to request clarification or add additional context in comments.

1 Comment

just for not creating duplicate answers, using reflection is just like doing new ArrayList<Object>() because a "generic class" is interpreted as an Object at runtime
7

There's no need to do any reflection for creating your List. Just pass in some additional type information (usually done by passing a class of the correct type).

public static <T> List<T> createListOfType(Class<T> type) {
    return new ArrayList<T>();
}

Now you have a list of the required type you can presumably/hopefully set it directly on your targetObject without any reflection.

Comments

2

Generics are a compile-time only "trick".

Reflection is runtime-only.

Basically, you can't - you can only create a "raw" ArrayList. If you need to pass it into methods that take generic parameters, casting it directly after construction will be safe (regardless of the "unchecked" warning). In this example, there's no compile-time type safety anyway due to using general Objects, so no casting is needed.

1 Comment

Generics is not completely a compile-time only thing. Concrete type parameters in field, method and class definitions are actually present in the bytecode and can be acquired at runtime via reflection.
0

Generics only work at compile time, therefore if you're using reflection, they won't be available.

See more about this here.

Comments

0

An object doesn't know about its generic type at execution time. Just create a new instance of the raw type (java.util.ArrayList). The target object won't know the difference (because there isn't any difference).

Comments

0

Generics is largely a compile time feature. What you are trying to do is the same as

public static void initializeList(Object targetObject, PropertyDescriptor prop, String gtype) {
    prop.getWriteMethod().invoke(targetObject, new ArrayList());
}

Note: This could change with Types in Java 7.

Comments

0

This can init a Object contains List successfully.

package com.y24.init;

import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import lombok.SneakyThrows;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

public class ObjInit {
    @SneakyThrows
    public static void main(String[] args) {
        Object o = objInit(Persons.class);
    }

    @SneakyThrows
    public static Object objInit(Class<?> clazz) {
        //基础数据类型
        if (clazz == int.class || clazz == Integer.class) {
            Object defaultValue = 1;
            return defaultValue;
        } else if (clazz == long.class || clazz == Long.class) {
            Object defaultValue = 1L;
            return defaultValue;
        } else if (clazz == double.class || clazz == Double.class) {
            Object defaultValue = 3.14;
            return defaultValue;
        } else if (clazz == boolean.class || clazz == Boolean.class) {
            Object defaultValue = false;
            return defaultValue;
        } else if (clazz == String.class) {
            Object defaultValue = "Hello world!";
            return defaultValue;
        }

        Object obj = null;
        try {
            obj = clazz.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 首先得到pojo所定义的字段
        Field[] fields = clazz.getDeclaredFields();
        for (Field curField : fields) {
            // 设置字段可访问(必须,否则报错)
            curField.setAccessible(true);

            Class<?> curFieldType = curField.getType();
            // 集合List元素
            if (curFieldType.equals(List.class)) {
                // 当前集合的泛型类型
                Type genericType = curField.getGenericType();
                if (genericType instanceof ParameterizedType) {
                    ParameterizedType pt = (ParameterizedType) genericType;
                    // 得到泛型里的class类型对象
                    Class<?> actualTypeArgument = (Class<?>) pt.getActualTypeArguments()[0];
                    List<Object> curEleList = new ArrayList<>();
                    //Object actualType = actualTypeArgument.newInstance();
                    //....actualType字段处理
                    Object actualType = objInit(actualTypeArgument);
                    curEleList.add(actualType);
                    curField.set(obj, curEleList);
                }
            } else {
                curField.set(obj, objInit(curFieldType));
            }
        }
        System.out.println(JSONObject.toJSONString(obj));
        return obj;
    }
}

@Data
class Persons {
    private int count;
    private List<Person> persons;
}

@Data
class Person {
    private String name;
    private int age;
    private Address address;
    private List<String> names;
}

@Data
class Address {
    private String city;
    private String zipCode;

    // getters and setters...
}

1 Comment

Can you please translate the comments? Could be helpful.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.