2010-03-09 25 views
56

En un conjunto de pruebas de aplicación para Android que tengo una clase como esta, donde B es una vista:¿Cómo comprobar si una subclase es una instancia de una clase en tiempo de ejecución?

public class A extends B { 
... etc... 
} 

ahora tengo una lista de objetos de vista que pueden contener A objetos, pero en este caso sólo se preocupan si están re subclases o "instancias de" B. Me gustaría hacer algo como:

ArrayList<View> viewList = getViews(); 
Iterator<View> iterator = viewList.iterator(); 
while (iterator.hasNext() && viewList != null) { 
    View view = iterator.next(); 
    if (view.getClass().isInstance(B.class)) { 
     // this is an instance of B 
    } 
} 

El problema es que cuando el if se encuentra con un objeto A que no se evalúa como una "instancia de B". ¿Hay alguna manera de hacer isSubclassOf o algo así?

+1

si el array viewlist es nula, entonces se bloquea el programa, incluso el registro de entrada, mientras que no ayuda. – Tim

+2

De Effective C++, por Scott Meyers: "Cada vez que se encuentre escribiendo código de la forma" si el objeto es de tipo T1, luego haga algo, pero si es de tipo T2, luego haga otra cosa, "bótete". No use un método reemplazado en su lugar? O tal vez algo así como el patrón visitante. – ishmeister

+1

Es para un caso de prueba por lo que el código no está realmente en la aplicación de producción, es para comprobar que las cosas estén usando las clases correctas :) – iamamused

Respuesta

136

Debes leer la API detenidamente para conocer estos métodos. A veces puedes confundirte muy fácilmente.

Es bien:

if (B.class.isInstance(view)) 

API dice: Determina si el objeto especificada(el parámetro) es con el objeto representado por esta clase(El objeto de la clase que una asignación compatible se llama al método a)

o:

if (B.class.isAssignableFrom(view.getClass())) 

API dice: Determina si la clase o interfaz representado por este objeto Clase es o bien el mismo que, o es una superclase o superinterfaz de, la clase o interfaz representado por la especificado parámetro Clase

o (sin reflexión y el recomendar uno):

if (view instanceof B) 
+9

+1 para if (ver instancia de B). Simple y funciona. –

+10

Tenga en cuenta que 'instanceof' no funcionará para genéricos debido a borrado. – Qix

+1

@Qix Gracias por la información. Las eliminaciones son un dolor en más de una parte del cuerpo, pero trabajar sin genéricos es peor. – Hardcoded

21
if(view instanceof B) 

Esto devolverá verdadero si la vista es una instancia de B o la subclase A (o cualquier subclase de B para el caso).

+2

Me gustaría mencionar que B debe importarse en el archivo .java actual para que esto funcione. Eclipse marcará la línea como que tiene un error pero no ofrece soluciones útiles de lo contrario (perdí casi una hora probando una sintaxis diferente antes de darme cuenta de que no había importado el archivo de la clase). Para cualquiera que se pregunte, la sintaxis correcta es ((nombre de instancia) instanceof (nombre de clase)). La clase de palabra no aparece en ninguna parte. – ArtOfWarfare

8

Tal vez me falta algo, pero no haría esto suficiente:

if (view instanceof B) { 
    // this view is an instance of B 
} 
2

Es al revés: B.class.isInstance(view)

-1

En realidad nunca he utilizado este, pero trate de view.getClass().getGenericSuperclass()

+1

El método está mal nombrado y documentado. No ayudará con el problema, ya que ni A ni B tienen genéricos. – Hardcoded

0

Si hay polimorfismo como la comprobación de SQLRecoverableException vs excepción de SQL, se puede hacer así.

try { 
    // sth may throw exception 
    .... 
} catch (Exception e) { 
    if(SQLException.class.isAssignableFrom(e.getCause().getClass())) 
    { 
     // do sth 
     System.out.println("SQLException occurs!"); 
    } 
} 

decir simplemente

ChildClass child= new ChildClass(); 
if(ParentClass.class.isAssignableFrom(child.getClass())) 
{ 
    // do sth 
    ... 
} 
+1

No haga algo como detectar Excepciones y verificar la clase de la excepción, si no tiene un motivo REALMENTE bueno. hacer en su lugar: '} catch (SQLException e) { } catch (Excepción e) { }' – Hardcoded

Cuestiones relacionadas