Reputation: 3539
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
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
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
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
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
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