2008-09-09 15 views
24

Digamos que tengo la clase siguiente:Java Genéricos: Comparación de la clase de objeto o de <E>

public class Test<E> { 
    public boolean sameClassAs(Object o) { 
     // TODO help! 
    } 
} 

¿Cómo puedo comprobar que el o es la misma clase que E?

Test<String> test = new Test<String>(); 
test.sameClassAs("a string"); // returns true; 
test.sameClassAs(4); // returns false; 

No puedo cambiar la firma del método de (Object o) como estoy overridding una superclase y así no se llega a elegir mi método de firma.

Yo también preferiría no ir por el camino de intentar un reparto y luego atrapar la excepción resultante si falla.

Respuesta

26

Una instancia de Test no tiene información sobre lo que es E en tiempo de ejecución. Por lo tanto, debe pasar un Class<E> al constructor de Prueba.

public class Test<E> { 
    private final Class<E> clazz; 
    public Test(Class<E> clazz) { 
     if (clazz == null) { 
      throw new NullPointerException(); 
     } 
     this.clazz = clazz; 
    } 
    // To make things easier on clients: 
    public static <T> Test<T> create(Class<T> clazz) { 
     return new Test<T>(clazz); 
    } 
    public boolean sameClassAs(Object o) { 
     return o != null && o.getClass() == clazz; 
    } 
} 

Si desea una relación "instanceof", utilice Class.isAssignableFrom en lugar de la comparación Class. Tenga en cuenta que E tendrá que ser un tipo no genérico, por el mismo motivo Test necesita el objeto Class.

Para ver ejemplos en la API de Java, consulte java.util.Collections.checkedSet y similares.

+1

prefiero comparo con las clases iguales. ¿O hay una razón especial para usar ==? – ordnungswidrig

+1

Son equivalentes. IMO == es más fácil de leer (aunque significa que el lector debe saber sobre el tipo). Es fraccionalmente más rápido antes de la línea. Ahora, lo que no parece haber probado es un clamor nulo. –

2

sólo podía hacer que funcione de esta manera:

public class Test<E> { 

    private E e; 

    public void setE(E e) { 
     this.e = e; 
    } 

    public boolean sameClassAs(Object o) { 

     return (o.getClass().equals(e.getClass())); 
    } 

    public boolean sameClassAs2(Object o) { 
     return e.getClass().isInstance(o); 
    } 
} 
9

El método que he utilizado siempre está por debajo. Es un dolor y un poco feo, pero no he encontrado uno mejor. Debe pasar el tipo de clase en la construcción, ya que cuando se compila Generics, la información de la clase se pierde.

public class Test<E> { 
    private Class<E> clazz; 
    public Test(Class<E> clazz) { 
     this.clazz = clazz; 
    } 
    public boolean sameClassAs(Object o) { 
     return this.clazz.isInstance(o); 
    } 
} 
-1

Solo intentaba hacer lo mismo, y un truco ingenioso que acabo de darme cuenta es que puedes probar un yeso, y si el lanzamiento falla, se lanzará ClassCastException. Puedes atrapar eso y hacer lo que sea.

por lo que su método sameClassAs debe verse como:

public boolean sameClassAs(Object o) { 
    boolean same = false; 
    try { 
     E t = (E)o; 
     same = true; 
    } catch (ClassCastException e) { 
     // same is false, nothing else to do 
    } finally { 
     return same; 
    } 
} 
+3

No, no lo hará. Eso es un elenco sin control. Nunca lanzará una excepción. En tiempo de ejecución, "t" tiene el tipo de borrado de E, que es solo Object, por lo que no se realiza ningún cast. – newacct

+0

Tiene razón. Eso me ahorraría toneladas de solución de problemas más tarde, porque la compilación parece estar bien. – Ayman

Cuestiones relacionadas