Que signifie le terme «forme canonique» ou «représentation canonique» en Java?

90

J'ai souvent entendu ce terme être utilisé, mais je ne l'ai jamais vraiment compris.

Qu'est-ce que cela signifie, et quelqu'un peut-il donner des exemples / me diriger vers des liens?

EDIT: Merci à tous pour les réponses. Pouvez-vous également me dire en quoi la représentation canonique est utile dans les performances equals (), comme indiqué dans Effective Java?

Shivasubramanian A
la source

Réponses:

56

Wikipédia pointe vers le terme canonisation .

Un processus pour convertir des données qui ont plus d'une représentation possible en une représentation canonique «standard». Cela peut être fait pour comparer différentes représentations d'équivalence, pour compter le nombre de structures de données distinctes, pour améliorer l'efficacité de divers algorithmes en éliminant les calculs répétés, ou pour permettre d'imposer un ordre de tri significatif.

L' exemple Unicode me semblait le plus logique:

Les encodages de longueur variable dans la norme Unicode, en particulier UTF-8, ont plus d'un encodage possible pour les caractères les plus courants. Cela rend la validation de chaîne plus compliquée, car chaque encodage possible de chaque caractère de chaîne doit être pris en compte. Une implémentation logicielle qui ne prend pas en compte tous les encodages de caractères court le risque d'accepter des chaînes considérées comme invalides dans la conception de l'application, ce qui pourrait provoquer des bogues ou permettre des attaques. La solution est de permettre un seul encodage pour chaque caractère. La canonisation est alors le processus de traduction de chaque caractère de chaîne en son unique encodage autorisé. Une alternative est que le logiciel détermine si une chaîne est canonisée, puis la rejette si ce n'est pas le cas. Dans ce cas, dans un contexte client / serveur, la canonisation serait à la charge du client.

En résumé, une forme standard de représentation des données. À partir de ce formulaire, vous pouvez ensuite convertir en n'importe quelle représentation dont vous pourriez avoir besoin.

Brian Gianforcaro
la source
64

Je crois qu'il y a deux utilisations liées de la canonique: les formes et les instances.

Une forme canonique signifie que les valeurs d'un type particulier de ressource peuvent être décrites ou représentées de plusieurs manières, et l'une de ces manières est choisie comme forme canonique préférée. (Cette forme est canonisée , comme les livres qui en ont fait la Bible, et les autres formes ne le sont pas.) Un exemple classique de forme canonique est les chemins dans un système de fichiers hiérarchique, où un seul fichier peut être référencé de plusieurs manières. :

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 définition classique de la représentation canonique de ce fichier serait le dernier chemin. Avec des chemins locaux ou relatifs, vous ne pouvez pas identifier globalement la ressource sans informations contextuelles. Avec les chemins absolus, vous pouvez identifier la ressource, mais vous ne pouvez pas dire si deux chemins font référence à la même entité. Avec deux chemins ou plus convertis dans leurs formes canoniques, vous pouvez faire tout ce qui précède, et déterminer si deux ressources sont identiques ou non, si cela est important pour votre application (résolvez le problème d'aliasing ).

Notez que la forme canonique d'une ressource n'est pas une qualité de cette forme particulière elle-même; il peut y avoir plusieurs formes canoniques possibles pour un type donné comme les chemins de fichiers (disons, lexicographiquement d'abord les chemins absolus possibles). Un formulaire est simplement sélectionné comme forme canonique pour une raison d'application particulière, ou peut-être arbitrairement afin que tout le monde parle la même langue.

Forcer des objets dans leurs instances canoniques est la même idée de base, mais au lieu de déterminer une «meilleure» représentation d'une ressource, il choisit arbitrairement une instance d'une classe d'instances avec le même «contenu» que la référence canonique, puis convertit toutes les références à des objets équivalents pour utiliser la seule instance canonique.

Cela peut être utilisé comme une technique pour optimiser le temps et l'espace. S'il y a plusieurs instances d'objets équivalents dans une application, alors en les forçant tous à être résolus en tant qu'instance canonique unique d'une valeur particulière, vous pouvez éliminer toutes sauf une de chaque valeur, économisant de l'espace et éventuellement du temps puisque vous pouvez maintenant comparer ces valeurs avec l'identité de référence (==) par opposition à l'équivalence d'objet ( equals()méthode).

Un exemple classique d'optimisation des performances avec des instances canoniques consiste à réduire des chaînes avec le même contenu. L'appel String.intern()de deux chaînes avec la même séquence de caractères est garanti pour renvoyer le même objet String canonique pour ce texte. Si vous passez toutes vos chaînes à travers ce canonicalizer, vous savez que les chaînes équivalentes sont en fait des références d'objet identiques, c'est-à-dire des alias

Les types enum dans Java 5.0+ forcent toutes les instances d'une valeur d'énumération particulière à utiliser la même instance canonique dans une machine virtuelle, même si la valeur est sérialisée et désérialisée. C'est pourquoi vous pouvez utiliser if (day == Days.SUNDAY)en toute impunité en java si Daysest un type enum. Faire cela pour vos propres cours est certainement possible, mais il faut faire attention. Lisez Effective Java par Josh Bloch pour plus de détails et des conseils.

Dov Wasserman
la source
31

Un bon exemple pour comprendre la "forme / représentation canonique" est de regarder la définition du type de données du schéma XML de "booléen":

  • la "représentation lexicale" de booléen peut être l'une des suivantes: {true, false, 1, 0}alors que
  • la "représentation canonique" ne peut être que l'une des {true, false}

Ceci, en substance, signifie que

  • "true"et "1"soyez mappé à la repr. canonique. "true"et
  • "false"et "0"soyez mappé à la repro canonciale."false"

voir la définition du type de données du schéma XML w3 pour booléen

Michael Marton
la source
28

Le mot «canonique» n'est qu'un synonyme de «standard» ou «habituel». Cela n'a aucune signification spécifique à Java.

Dónal
la source
3
canonique a une signification plus riche que l'OMI standard ou habituelle.
calmar
20

réduit à la forme la plus simple et la plus significative sans perdre la généralité

Jaime
la source
5

Un moyen facile de s'en souvenir est la façon dont «canonique» est utilisé dans les cercles théologiques, la vérité canonique est la vraie vérité, donc si deux personnes la trouvent, elles ont trouvé la même vérité. Idem avec l'instance canonique. Si vous pensez en avoir trouvé deux (ie a.equals(b)), vous n'en avez vraiment qu'un (ie a == b). L'égalité implique donc l'identité dans le cas d'un objet canonique.

Maintenant pour la comparaison. Vous avez maintenant le choix d'utiliser a==b ou a.equals(b) , car ils produiront la même réponse dans le cas d'une instance canonique mais a == b est la comparaison de la référence (la JVM peut comparer deux nombres extrêmement rapidement car ce ne sont que deux modèles de 32 bits comparés à a.equals(b)qui est un appel de méthode et implique plus de frais généraux.

Chris Mawata
la source
2

Un autre bon exemple pourrait être: vous avez une classe qui prend en charge l'utilisation des coordonnées cartésiennes (x, y, z), sphériques (r, thêta, phi) et cylindriques (r, phi, z). Pour établir l'égalité (méthode égale), vous voudrez probablement convertir toutes les représentations en une représentation «canonique» de votre choix, par exemple des coordonnées sphériques. (Ou peut-être voudriez-vous faire cela en général - c'est-à-dire utiliser une représentation interne.) Je ne suis pas un expert, mais cela m'est venu à l'esprit comme peut-être un bon exemple concret.

Kimberley Coburn
la source
0

la représentation canonique signifie voir le caractère dans un style différent, par exemple si j'écris une lettre A signifie qu'une autre personne peut écrire la lettre A dans un style différent :)

Ceci est conforme au CHAMP DE RECONNAISSANCE DE CARACTERE OPTIQUE

SASIKALA
la source
0

Une forme canonique signifie une représentation naturellement unique de l'élément

Maksym Ovsianikov
la source
0

Les questions du PO sur la forme canonique et sur la manière dont elle peut améliorer les performances de la equalsméthode peuvent toutes deux être répondues en étendant l'exemple fourni dans Effective Java.

Considérez la classe suivante:

public final class CaseInsensitiveString {

  private final String s;

  public CaseInsensitiveString(String s) {
    this.s = Objects.requireNonNull(s);
  }

  @Override 
  public boolean equals(Object o) {
    return o instanceof CaseInsensitiveString && ((CaseInsensitiveString) o).s.equalsIgnoreCase(s);
  }
}

La equalsméthode de cet exemple a un coût supplémentaire en utilisant Stringla equalsIgnoreCaseméthode de. Comme mentionné dans le texte

vous voudrez peut-être stocker une forme canonique du champ afin que la méthode d'égalité puisse faire une comparaison exacte bon marché sur les formes canoniques plutôt qu'une comparaison non standard plus coûteuse.

Que veut dire Joshua Bloch quand il parle de forme canonique ? Eh bien, je pense que la réponse concise de Dónal est très appropriée. Nous pouvons stocker le Stringchamp sous-jacent dans l' CaseInsensitiveStringexemple de manière standard , peut-être la forme majuscule du String. Maintenant, vous pouvez référencer cette forme canonique du CaseInsensitiveString, sa variante majuscule, et effectuer des évaluations bon marché dans vos méthodes equalset hashcode.

Le poignard Gilbert Arenas
la source
0

Données canoniques dans le SGBDR, données graphiques;
Pensez à la «normalisation» ou à la «forme normale» d'une donnée dans un SGBDR. Les mêmes données existent dans différentes tables, représentées par un identifiant unique et mappées dans différentes tables.
ou
Pensez à une forme unique de données dans la base de données Graph qui est représentée en plusieurs triplets.

Son principal avantage est de rendre Dml (manipulation de données) plus efficace car vous ne pouvez insérer (insérer / mettre à jour) qu'une seule valeur au lieu de plusieurs.

Alper t. Turker
la source