Una forma de responder a su pregunta sería responder "¿cuándo una biblioteca sólida de Java usa instanceof
?"Si suponemos que Guava es un ejemplo de una biblioteca Java bien diseñada, podemos ver dónde utiliza instanceof
para decidir cuándo es aceptable hacerlo.
Si extraemos el código fuente de la jarra de guayaba y grep, vemos instanceof
se menciona 439 veces, a través de 122 archivos:
$ pwd
/tmp/guava-13.0.1-sources
$ grep -R 'instanceof' | wc -l
439
$ grep -Rl 'instanceof' | wc -l
122
Y mirando a algunos de estos casos podemos ver varios patrones emergen:
para comprobar la igualdad
Este es el uso más común. Esto es algo específico de la implementación, pero suponiendo que de hecho desea medir la igualdad en función de la clase/interfaz que amplía/implementa, puede usar instanceof
para asegurarse de que el objeto con el que trabaja es. Sin embargo, esto puede causar problemas extraños si una clase secundaria anula equals()
y no respeta los mismos requisitos instanceof
que el padre. Ejemplos en todas partes, pero uno fácil es Lists.equalsImpl()
que es utilizado por ImmutableList
.
Para cortocircuito construcción de objetos innecesarios
Puede utilizar instanceof
para comprobar si la pasaron en el argumento puede ser utilizado o devuelto de forma segura sin transformar aún más que, por ejemplo, si ya una instancia de la deseada clase, o si sabemos que es inmutable. Véanse los ejemplos en CharMatcher.forPredicate()
, Suppliers.memoize()
, ImmutableList.copyOf()
, etc.
Para acceder a los detalles de implementación-sin exponer comportamiento diferente
Esto puede ser visto por todo el lugar en la guayaba, pero sobre todo en las clases de utilidad en estáticas el paquete com.google.common.collect
, por ejemplo en Iterables.size()
donde llama a Collection.size()
si es posible, y de lo contrario cuenta el número de elementos en el iterador en el tiempo O(n)
.
Para evitar llamar toString()
Soy escéptico esto merece que se realiza en más de un muy selecto pocos casos, pero suponiendo que esté seguro de que está haciendo lo correcto, se puede evitar la innecesaria Convirtiendo CharSequence
objetos en String
s con , como se hace en Joiner.toString(Object)
.
Para ello manejo complejo
Obviamente lo "correcto" que hacer es utilizar un bloque try/catch
(aunque en realidad, que está haciendo instanceof
cheques ya) Excepción, pero a veces hay lógica de manejo más complejo que merece usar bloques condicionales o pasar el procesamiento a un método separado, por ejemplo, extraer causas o tener un procesamiento específico de la implementación. Se puede encontrar un ejemplo en SimpleTimeLimiter.throwCause()
.
Una cosa que se destaca mirando este comportamiento es problemas casi todos ellos están abordando que no debería estar resolviendo. Son útiles en el código de la biblioteca, p. en Iterables
, pero si estoy implementando este comportamiento, probablemente debería preguntarme si no hay bibliotecas o utilidades que resuelvan esto por mí.
En todos los casos, yo diría que instanceof
cheques solamente nunca deben usarse internamente como un detalle de implementación - es decir, la persona que llama de cualquier método que se basa en una comprobación instanceof
no debería ser capaz de (fácilmente) dicen que es que hiciste. Por ejemplo, ImmutableList.copyOf()
siempre devuelve ImmutableList
. Como detalle de implementación, usa instanceof
para evitar la construcción de nuevos ImmutableList
s, pero eso no es necesario para proporcionar de manera aceptable el comportamiento esperado.
Como un lado, fue divertido encontrar tu nombre, Louis, mientras estaba cavando a través del código fuente de Guava. ¡Juro que no tenía ni idea!
Hmmmmm. ¿Algún ejemplo en mente? No he encontrado esa necesidad con ninguna API con la que haya jugado. –
@LouisWasserman Cualquier cosa escrita de forma no OO, por ejemplo, teníamos una API de terceros donde varias clases FTP no extendían una clase base común ni implementaban una interfaz. Para tratarlos de la misma manera, nuestra solución rápida fue una instancia trivial de verificación. Finalmente colocamos una capa sobre la parte superior. Hay un montón de malas API en el mundo. –
Ew. Supongo que debería estar agradecido por no haber tenido que lidiar con ninguna de esas bestias. –