¿Se lo considera una mala práctica? Si es así, ¿bajo qué circunstancias es aún preferible una instancia?

Con los años, he tratado de evitar la instanceof siempre que sea posible. Usar polymorphism o el patrón de visitante cuando corresponda. Supongo que simplemente facilita el mantenimiento en algunas situaciones … ¿Hay algún otro inconveniente que uno debe tener en cuenta?

Sin embargo, lo veo aquí y allá en las bibliotecas de Java, así que supongo que tiene su lugar? ¿En qué circunstancias es preferible? ¿Es alguna vez inevitable?

Puedo imaginar algunos casos, por ejemplo, tiene algunos objetos de una biblioteca, que no puede ampliar (o sería inconveniente hacerlo), tal vez mezclados con algunos objetos de su, todos con la misma clase base, juntos en una colección.
Supongo que en tal caso, usar instanceof para distinguir algún procesamiento en estos objetos podría ser útil.

Idem en algunos mantenimiento de código heredado donde no se puede inyectar un nuevo comportamiento en muchas clases antiguas solo para agregar una nueva característica pequeña o alguna corrección de errores …

Definitivamente tiene su lugar en una implementación de stock de equals . P.ej

 public boolean equals ( Object o ) { if ( this == o ) { return true; } if ( ! (o instanceof MyClass) ) { return false; } // Compare fields ... } 

Una cosa interesante de saber de instanceof es que su LHS puede ser null y en ese caso la expresión se evalúa como false .

Creo que cuando necesitas absolutamente saber el tipo de objeto, instanceof es la mejor opción disponible.

Una mala práctica sería tener muchas instanceof s, una al lado de la otra, y según ellas, llamar a diferentes métodos de los objetos (por supuesto, casting). Esto probablemente reflejaría que la jerarquía necesita un replanteamiento y probablemente una refactorización.

Cuando estás dentro de un modelo OO puro, entonces instanceof es definitivamente un olor a código.

Sin embargo, si no está utilizando un modelo 100% OO o necesita inyectar cosas desde el exterior, entonces instancia de o equivalentes ( isXXX() , getType() , …) puede tener sus usos.

La “regla” general sería evitarla siempre que sea posible, especialmente cuando se controla la jerarquía de tipos y se puede usar un polymorphism de subtipo, por ejemplo. La idea no es preguntar al objeto qué tipo es y hacer algo con él, sino más bien preguntar al objeto directa o indirectamente a través de un visitante (esencialmente polymorphism doble) para realizar alguna acción.

Se puede usar como control de cordura antes de lanzar; además de verificar que tu objeto sea del tipo correcto, también verifica que no sea nulo.

 if (o instanceof MyThing) { ((MyThing) o).doSomething(); // This is now guaranteed to work. } else { // Do something else, but don't crash onto ClassCast- or NullPointerException. } 

Estoy de acuerdo que puede tener un mal olor. Muchos de los casos, especialmente en un bloque encadenado si huelen mal.

A veces puede comportarse de una manera que no esperarías … Algo que sucedió una vez:

 Class B extends A Class C extends A B b = new B(); C c = new C(); b instanceof B -> true b instanceof C -> true c instanceof C -> true c instanceof B -> true 

(en mi caso esto sucedió debido a hibernación haciendo objetos proxy … pero solo un caso en el que el código que depende de instanceof es arriesgado)

¿Qué tal en el caso de una fábrica de creación? p.ej

 public static Cage createCage(Animal animal) { if (animal instanceof Dog) return new DogHouse(); else if (animal instanceof Lion) return new SteelCage(); else if (animal instanceof Chicken) return new ChickenWiredCage(); else if (animal instanceof AlienPreditor) return new ForceFieldCage(); ... else return new GenericCage(); }