java acquiring arraylist component type from method parameter of arraylist<T>

I've been trying to figure a way of determining an ArrayList's component type when passed to a static method as a parameter. My current attempt has resulted in this:

public static <T> Class getArrayListClass(ArrayList<T> al) {
    Class clazz = null;
    for(T t: al) {
        if(t != null) {
            clazz = t.getClass();//Get first type found.
        }
    }
    return clazz;
}

Is there an alternative way of determining the type of an ArrayList? Better yet, how can I find the component types of an ArrayList with size 0? The static method does not know "who has ownership" of the ArrayList object, making reflections with fields difficult because (from what I been reading) you need to know where the container comes from (surely the original source would know it's type), or someone who has reference to a container like it of known type (Non type T) or simply know its type... There was a post about something similar, using Lists: Get generic type of java.util.List In there solutions, they were using reflection and stated that it could be done for parameters and return types as well, but there were no examples of type T parameters... The second best answer on that link showed an example of acquiring the type from method parameters, but of non type T, which in my case, I am acquiring the ArrayList as a type T parameter. Any favorable solutions? My current method can only be applied to ArrayLists of size > 0. I've gotten types from primitive arrays before (fortunately): someArray.getClass().getComponentType()//T[] though they're vastly different, but that opens up one of my last two alternative options I'd already seen and would rather avoid: A) converting ArrayLists to arrays of known type (not objects) then when type is needed to be known by other methods/objects, they can unwrap it using the getComponentType method or B) always send the type as an extra parameter... Don't know if this is a duplicate, but I've looked a bit; if it is send me in the right direction. Thanks.

1 answer

  • answered 2018-05-16 05:24 sprinter

    I suspect you are misunderstanding how Java generics work. The design of generics had as an objective that there be no runtime overhead of having generic classes with multiple types instantiated. In other words, it is really only one class under the covers, with the parameterised type available only during the compile phase: at runtime the parameterised type disappears. This is known as erasure. See here for a tutorial on how it works.

    In your case this means that it is literally impossible to find the real type of T at runtime (which is when reflection is in operation) because there is no real type at runtime. It has been erased.

    In your code you are passing an object to a method which has a real type and you can use reflection to find its type.

    Keep in mind that use of reflection is nearly always an indication of bad design. There are a few cases where it's necessary (e.g. serialisation of objects) but in the vast majority of cases there are better ways to achieve an outcome.