17

Given an Object o and a String className = "org.foo.Foo", I want to check if o is instance of List<className>

I tried this but won't compile:

Class<?> cls = Class.forName(className);
if (o instanceof List<cls>){ // this gives error: cls cannot be resolved to a type
  doSomething();
}

Please note that my inputs are Object o and String className (please mind types).

2
  • 1
    Generics are erased at runtime. What you are trying to do seems impossible. Can you explain why you want to do it? Maybe it is XY problem. Commented Jul 28, 2014 at 20:29
  • I'm dynamically instantiating objects while parsing XML with SAX Commented Jul 28, 2014 at 20:34

6 Answers 6

11

It's because of Type Erasure. The statement

if (o instanceof List<cls>) {
  doSomething();
}

will be executed at runtime, when the generic type of the list will be erased. Therefore, there's no point of checking for instanceof generic-type.

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

3 Comments

ok you're explaining me why it doesn't work, but I still need to find a way to do the check...
@Iviggiani You can't. A program can't figure out what generics are being used, because generics don't exist at runtime.
@Iviggiani The only way to check the type of things contained in the list at runtime is to pull one out and look at it. If the list is empty, it is utterly impossible. That's why you see a lot of method signatures which look like doSomething(Thing first, Thing... theRest), which allows the method to explicitly set the type based on first, rather than something like doSomething(Thing... everything).
11

I think you can do it in two steps: First, you check it's a List.

if (o instanceof List)

Then, you check that one (each?) member of the list has the given type.

for (Object obj : (List) o) {
    if (obj instanceof cls) {
        doSomething();
    }
}

Comments

7

Solution i used in my project.

/**
 * Used to get List of String From Object.
 *
 * 1. used to convert object to list of String.
 * 
 * @param objectList Object List.
 * @return List Of String.
 */
private List<String> getListOfStringFromObject(final Object objectList) {
    List<String> stringList = new ArrayList<>();
    if (objectList instanceof List<?>) {
        for (Object object : (List<?>) objectList) {
            if (object instanceof String) {
                stringList.add((String) object);
            }
        }
    }
    return stringList;
}

Comments

6

Ok, I found a method... it's a little dirty code but it works:

if (o instanceof List<?>){
  ParameterizedType pt = (ParameterizedType)o.getClass().getGenericSuperclass();
  String innerClass = pt.getActualTypeArguments()[0].toString().replace("class ", "");
  System.out.println(innerClass.equals(className)); // true
}

1 Comment

Tried this to assert type of MyObject<MyType>, but couldn't get it to work. It throws class cast exception when trying to cast to ParameterizedType.
2
public class Main{

    public static void main(String[] args){
        String str = "";
        int oi = 0;
        char c = 'a';
        Main af = new Main();
        checkType(str);
        checkType(oi);
        checkType(c);
        checkType(af);
    }

    public static void checkType(Object o){
        String str = o.getClass().getName();
        switch(str){
            case "java.lang.String":
                System.out.println("String");
                break;  
            case "java.lang.Integer":
                System.out.println("Integer");
                break;
            case "java.lang.Character":
                System.out.println("Char");
                break;
            case "Main":
                System.out.println("Main");
                break;
            default :
                System.out.println("Something else:" + str);
                break;
        }
    }

}

Note> just change to public static boolean checkType(Object o) and then return true in each case that isn't default.

Comments

0

if what you want to do is like this:

class XXX implements InterfaceX {
    @Override
    public void methedX() { }
}

interface InterfaceX {
    void methedX();
}
List<XXX> x = new ArrayList<>();

if(x instanceOf List<InterfaceX>) {
    data.get(0).methedX();
}

you may try to use template like:

class TypeHelper <T extends InterfaceX> {
    List<T> data;
    TypeHelper (List<T> data) {
        this.data = data;
    }

    public void func() {
        data.get(0).methedX();
    }
}

TypeHelper helper = new TypeHelper<XXX>(x);
helper.func();

Comments

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.