Creo que hay dos usos relacionados de canónico: formas e instancias.
Una forma canónica significa que los valores de un tipo particular de recurso se pueden describir o representar de múltiples formas, y una de esas formas se elige como la forma canónica preferida. (Esa forma está canonizada , como los libros que llegaron a la Biblia, y las otras formas no). Un ejemplo clásico de una forma canónica son las rutas en un sistema de archivos jerárquico, donde se puede hacer referencia a un solo archivo de varias maneras. :
myFile.txt # in current working dir
../conf/myFile.txt # relative to the CWD
/apps/tomcat/conf/myFile.txt # absolute path using symbolic links
/u1/local/apps/tomcat-5.5.1/conf/myFile.txt # absolute path with no symlinks
La definición clásica de la representación canónica de ese archivo sería la última ruta. Con rutas locales o relativas, no puede identificar globalmente el recurso sin información contextual. Con las rutas absolutas puede identificar el recurso, pero no puede saber si dos rutas se refieren a la misma entidad. Con dos o más rutas convertidas a sus formas canónicas, puede hacer todo lo anterior, además de determinar si dos recursos son iguales o no, si eso es importante para su aplicación (resuelva el problema del alias ).
Tenga en cuenta que la forma canónica de un recurso no es una cualidad de esa forma particular en sí; puede haber múltiples formas canónicas posibles para un tipo dado, como rutas de archivo (digamos, lexicográficamente en primer lugar de todas las posibles rutas absolutas). Una forma simplemente se selecciona como forma canónica por una razón de aplicación en particular, o tal vez arbitrariamente para que todos hablen el mismo idioma.
Forzar objetos en sus instancias canónicas es la misma idea básica, pero en lugar de determinar una "mejor" representación de un recurso, elige arbitrariamente una instancia de una clase de instancias con el mismo "contenido" que la referencia canónica, luego convierte todas las referencias a objetos equivalentes para usar la única instancia canónica.
Esto se puede utilizar como una técnica para optimizar tanto el tiempo como el espacio. Si hay varias instancias de objetos equivalentes en una aplicación, al forzarlos a que se resuelvan como la única instancia canónica de un valor particular, puede eliminar todos menos uno de cada valor, ahorrando espacio y posiblemente tiempo, ya que ahora puede comparar aquellos valores con identidad de referencia (==) en contraposición a la equivalencia de objeto ( equals()método).
Un ejemplo clásico de optimización del rendimiento con instancias canónicas es contraer cadenas con el mismo contenido. String.intern()Se garantiza que la invocación de dos cadenas con la misma secuencia de caracteres devolverá el mismo objeto String canónico para ese texto. Si pasa todas sus cadenas a través de ese canonicalizador, sabrá que las cadenas equivalentes son en realidad referencias de objetos idénticas, es decir, alias
Los tipos de enumeración en Java 5.0+ obligan a todas las instancias de un valor de enumeración particular a usar la misma instancia canónica dentro de una VM, incluso si el valor está serializado y deserializado. Es por eso que puede usar if (day == Days.SUNDAY)con impunidad en java si Dayses un tipo enum. Hacer esto para sus propias clases es ciertamente posible, pero hay que tener cuidado. Lea Effective Java de Josh Bloch para obtener detalles y consejos.