简体   繁体   中英

Can I get the type of an object in an ArrayList to instantiate a generic class?

I am not experienced in Java, but was tasked with an objective in my company that involves Java and I am looking for help.

I have two Eclipse Java projects: MyProject.Base and MyProject.Contracts with MyProject.Contracts referencing MyProject.Base. MyProject.Contracts contains a set of serializable classes.

MyProject.Base uses JAXB to (de-)serialize objects. In order to serialize ArrayLists with JAXB, I had to write the following class, because JAXB expects a XmlRootElement annotation for objects that shall be serialized and ArrayList does not offer that.

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(namespace = "http://schemas.microsoft.com/2003/10/Serialization/Arrays", name = "ListOfValuesOfAnyTypeAdapter")
public class ListConverterAdapter<E> {
    @XmlElement(namespace = "http://schemas.microsoft.com/2003/10/Serialization/Arrays", name = "ListOfValuesOfAnyType")
    List<E> Map;

    public ListConverterAdapter() {
        Map = new ArrayList<E>();
    }

    public ListConverterAdapter(Object value) {
        Map = new ArrayList<E>();

        @SuppressWarnings("unchecked")
        List<E> map = (List<E>) value;
        if (map == null) {
            return;
        }

        for (int i = 0; i < map.size(); i++) {
            Map.add(map.get(i));
        }
    }

    public List<E> GetHashMap() {
        List<E> map = new ArrayList<E>();

        for (int i = 0; i < Map.size(); i++) {
            map.add(Map.get(i));
        }

        return map;
    }
}

I want the serializer and this helper class to work with any list of any data contract to work. However, JAXB wants to know all the types that are used as E. I could simply add an annotation listing the data contracts, if I could reference MyProject.Contracts in MyProject.Base. However, as I explained earlier, there is already a reference from MyProject.Contracts to MyProject.Base. Meaning, I can't add the new reference, because it would create a circular reference.

I have done some search here and on other forums about instantiating a generic class like mine above at run-time. Unfortunately, I am not able to do so for two reasons. First, as far as I have read in the past days, it is not possible to get to know the type of objects in an empty Java list. Second, even if I get the class type of an object in a non-empty list, I can't use it to instantiate my generic class.

List<Object> list = (List<Object>) value;
if (list.size() > 0) {
    Class classType = list.get(0).getClass();

    ListConverterAdapter<classType> convert = new ListConverterAdapter<>(value);
}

Is there a way to instantiate a generic class with an object type of an empty or non-empty list in Java?

Is there a way to instantiate a generic class with an object type of an empty or non-empty list in Java?

No. At runtime, generic type information is no longer available, so List<T> is just List .

Here's a really simple example of a generic method. For some type <T> , it will return a List<T> which will be ArrayList<T> (really just ArrayList<> , without T ):

public static <T> List<T> run() {
    return new ArrayList<>();
}
  1. Invoke it like this, passing type info in the method invocation: GenericListExample.<String>run() (or GenericListExample.run() if you have a lefthand side of the statement with type info, like below)
  2. At compile time, you'll get a return type of this: List<String>
  3. At runtime, the resulting list that comes back is just ArrayList . Only at compile time is there any trace of the list containing String . After compilation, String is lost.

Here's the entire class:

public class GenericListExample {
    public static void main(String[] args) {
        List<String> list = GenericListExample.run();
        System.out.println("list.getClass(): " + list.getClass());
    }

    public static <T> List<T> run() {
        return new ArrayList<T>();
    }
}

And the output:

list.getClass(): class java.util.ArrayList

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM