Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check instance with java.lang.reflect.Type

I'm looking for a way to find out if an object x is an instance of a generic type. For example List<String>.

Inspired by the Super-Type-Token idiom I can retrieve the java.lang.reflect.Type at runtime with follwing code

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

public class Test {

    public static void main(String[] args) {
        TypeReference<List<String>> ref = new TypeReference<List<String>>() {};
        System.out.println(ref.getType());
        System.out.println(ref.getType().getClass());
    }

    abstract static class TypeReference<T> {
        private final Type type;

        protected TypeReference() {
            ParameterizedType superclass = (ParameterizedType) getClass().getGenericSuperclass();
            type = superclass.getActualTypeArguments()[0];
        }

        public Type getType() {
            return type;
        }
    }
}

The output is

java.util.List<java.lang.String>
class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl

How can I use this information for dynamic casting or type checking?

Background is I'm currently writing a heterogeneous type-safe container lib and want to add support for generic types https://bitbucket.org/mbeyene/jam

like image 220
mike Avatar asked Sep 10 '26 05:09

mike


1 Answers

You must notice that you're using a parameterized type as type argument for TypeReference<T> instance. So you would need to cast it to ParameterizedType at the caller end, and get the raw type from that.

Then you can cast that rawtype to Class<?> type, and use Class#isInstance() method:

public static void main(String[] args) {
    TypeReference<List<String>> ref = new TypeReference<List<String>>() {};

    List<String> list = new ArrayList<String>();

    Type rawType = ((ParameterizedType)ref.getType()).getRawType();
    boolean listIsInstanceOfRawType = ((Class<?>)(rawType)).isInstance(list));

    System.out.println(listIsInstanceOfRawType); // true
}

Note that, you can't check instanceof against a parameterized type - List<String> or List<Integer>, as that doesn't make sense. Both of them are nothing but List at runtime. What I mean is:

List<String> list = new ArrayList<String>();

System.out.println(list instanceof List<String>);  // Won't compile
System.out.println(list instanceof List);          // You've to do this.

// The reason is, this is true
System.out.println(new ArrayList<String>().getClass() == new ArrayList<Integer>().getClass());   // true
like image 142
Rohit Jain Avatar answered Sep 12 '26 19:09

Rohit Jain