Adibe7
Adibe7

Reputation: 3539

how to compare type of an object's instance to a generic type?

how can i write this code in java?

public class ComponentsManager 
    {
        private List<IComponent> list = new ArrayList<IComponent>();

        public <U extends IComponent> U GetComponent() {

            for (IComponent component : list) {

                if(component instanceof U)
                {
                    return component;
                }
            }
        }
}

but i cant perform instanceof on generic types. how should i do it? thanks.

Upvotes: 18

Views: 27767

Answers (5)

千木郷
千木郷

Reputation: 1807

Exactly generic type can't be treated as a normal variable in code, which makes it hard to do comparing directly. However the reflective class, ParameterizedType, could help you get an instance representing a parameterized type, which is basically practicable objects.

Type genericSuperType = object.getClass().getGenericSuperclass()
Type[] actualTypeParams = ((ParameterizedType) genericSuperType).getActualTypeArguments()
if (actualTypeParams[0] instanceof Class) {
    ((Class) actualTypeParams[0]).isInstance(testingObj);
}

For more details about the usage upon ParameterizedType and corresponding TypeVariable, the internal util class, TypeParameterMatcher`, in Netty could be referenced.

Upvotes: 0

Hosam Aly
Hosam Aly

Reputation: 42443

As far as I know, you can't. You'll have to take a Class object as a parameter:

public <U extends IComponent> U getComponent(Class<U> clazz) {
    // ...
    if (component.getClass() == clazz) {
        return (U) component;
    }
}

And call it like this:

getComponent(MyComponentImpl.class);

Upvotes: 2

Andreas Dolk
Andreas Dolk

Reputation: 114767

General rule with java - if a generic class needs to know its generic type(s), then you have to pass a hint. A common approach for the problem is using the constructor:

public class ComponentsManager<U extends IComponent> {
  private Class<U extends IComponentManeger> genericType = null;
  public ComponentsManager<U extends IComponent>(
                       Class<U extends IComponent> genericType) {
    this.genericType = genericType;
  }

}

Now the class knows it's generic type class and you can uses the generic type class instance to verify, if a component in your collection matches the classes generic type.

Upvotes: 2

sje397
sje397

Reputation: 41822

You could try adding a couple of 'test' methods:

private static <U extends IComponent> boolean testComponent(U u) {
  return true;
}

private static boolean testComponent(Object o) {
  return false;
}

Then, use testComponent(component) instead of component instanceof U.

Example code:

import java.util.*;

class IComponent {
}

class T1 extends IComponent {
}

public class Test {

  public static <U extends IComponent> boolean testComponent(U u) {
    return true;
  }

  public static boolean testComponent(Object o) {
    return false;
  }

  public static void main(String[] args) {
    T1 t = new T1();
    System.out.println("hm? " + (testComponent(t) ? "true" : "false"));
  }
}

Output:

hm? true

Upvotes: 2

Stephen C
Stephen C

Reputation: 718798

Basically you can't do that due to type erasure. The normal workaround is to pass a Class object as a parameter; e.g.

    public <U extends IComponent> U GetComponent(Class<U> clazz) {
        for (IComponent component : list) {
            if (clazz.isInstance(component)) {
                return clazz.cast(component);
            }
        }
    }

You could also use if (clazz.equals(component.getClass())) { ... but that does an exact type match ... which is not what the instanceof operator does. The instanceof operator and the Class.instanceOf method both test to see if the value's type is assignment compatible.

Upvotes: 27

Related Questions