it-swarm.com.de

Was bedeutet der Begriff "kanonische Form" oder "kanonische Darstellung" in Java?

Ich habe oft gehört, dass dieser Begriff verwendet wurde, aber ich habe ihn nie wirklich verstanden.

Was bedeutet das, und kann jemand auf einige Links verweisen?

EDIT: Danke an alle für die Antworten. Können Sie mir auch sagen, wie nützlich die kanonische Darstellung in der Leistung von equals () ist, wie in Effective Java angegeben?

78

Wikipedia verweist auf den Begriff Kanonisierung .

Ein Prozess zum Konvertieren von Daten, die mehr als eine mögliche Darstellung haben, in eine "kanonische" Standarddarstellung. Dies kann durchgeführt werden, um verschiedene Repräsentationen auf Äquivalenz zu vergleichen, die Anzahl der unterschiedlichen Datenstrukturen zu zählen, die Effizienz verschiedener Algorithmen zu verbessern, indem wiederholte Berechnungen eliminiert werden, oder um eine sinnvolle Sortierreihenfolge festzulegen.

Das Beispiel Unicode war für mich am sinnvollsten:

Kodierungen mit variabler Länge im Unicode-Standard, insbesondere UTF-8, enthalten mehr als eine Kodierung für die meisten gebräuchlichen Zeichen. Dies macht die Stringsvalidierung komplizierter, da jede mögliche Codierung jedes Strings berücksichtigt werden muss. Bei einer Software-Implementierung, die nicht alle Zeichencodierungen berücksichtigt, besteht das Risiko, dass im Anwendungsdesign als ungültig eingestufte Zeichenfolgen akzeptiert werden. Dies kann zu Fehlern oder Angriffen führen. Die Lösung besteht darin, für jedes Zeichen eine einzige Kodierung zuzulassen. Kanonisierung ist dann der Prozess, bei dem jedes Zeichenfolgenzeichen in seine einzige zulässige Kodierung übersetzt wird. Eine Alternative besteht darin, dass die Software ermittelt, ob eine Zeichenfolge kanonisiert ist, und sie dann zurückweist, wenn dies nicht der Fall ist. In diesem Fall liegt die Kanonisierung in einem Client/Server-Kontext im Verantwortungsbereich des Clients.

Zusammenfassend eine Standarddarstellung für Daten. Von diesem Formular aus können Sie dann in jede gewünschte Darstellung konvertieren. 

52

Ich glaube, es gibt zwei verwandte Verwendungen von Kanonikern: Formen und Instanzen.

Ein kanonische Form bedeutet, dass Werte eines bestimmten Ressourcentyps auf verschiedene Arten beschrieben oder dargestellt werden können. Eine dieser Möglichkeiten wird als bevorzugte kanonische Form gewählt. (Diese Form ist kanonisiert, wie Bücher, die es in die Bibel geschafft haben, und die anderen Formulare sind nicht.) Ein klassisches Beispiel für eine kanonische Form sind Pfade in einem hierarchischen Dateisystem, in denen eine einzelne Datei referenziert werden kann eine Reihe von Möglichkeiten:

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

Die klassische Definition der kanonischen Darstellung dieser Datei wäre der letzte Pfad. Mit lokalen oder relativen Pfaden können Sie die Ressource ohne Kontextinformationen nicht global identifizieren. Mit absoluten Pfaden können Sie die Ressource identifizieren, können jedoch nicht feststellen, ob zwei Pfade auf dieselbe Entität verweisen. Mit zwei oder mehr Pfaden, die in ihre kanonischen Formen umgewandelt wurden, können Sie alle oben genannten Schritte ausführen und feststellen, ob zwei Ressourcen gleich sind oder nicht, ob dies für Ihre Anwendung wichtig ist (lösen Sie das Aliasing-Problem).

Beachten Sie, dass die kanonische Form einer Ressource nicht die Qualität dieser bestimmten Form selbst ist. Es gibt mehrere mögliche kanonische Formen für einen bestimmten Typ wie Dateipfade (zum Beispiel lexikographisch zuerst mögliche absolute Pfade). Ein Formular wird nur aus einem bestimmten Anwendungsgrund als kanonisches Formular ausgewählt oder möglicherweise willkürlich, so dass alle dieselbe Sprache sprechen.

Das Erzwingen von Objekten in ihre kanonischen Instanzen ist dieselbe Grundidee, aber anstatt eine "beste" Darstellung einer Ressource zu bestimmen, wählt sie willkürlich eine Instanz einer Klasse von Instanzen mit demselben "Inhalt" wie der kanonische Referenz konvertiert dann alle Referenzen in entsprechende Objekte, um die eine kanonische Instanz zu verwenden.

Dies kann als eine Technik zum Optimieren von Zeit und Raum verwendet werden. Wenn es mehrere Instanzen äquivalenter Objekte in einer Anwendung gibt, können Sie alle als einen kanonischen Instanzen eines bestimmten Werts auflösen, indem Sie sie alle als einen einzigen Wert eines bestimmten Werts auflösen, um Platz und möglicherweise Zeit zu sparen, da Sie jetzt vergleichen können diese Werte mit Referenzidentität (==) im Gegensatz zur Objektäquivalenz (equals()-Methode).

Ein klassisches Beispiel für die Optimierung der Leistung mit kanonischen Instanzen ist das Reduzieren von Zeichenfolgen mit demselben Inhalt. Wenn Sie String.intern() für zwei Zeichenfolgen mit derselben Zeichenfolge aufrufen, wird garantiert dasselbe kanonische Zeichenkettenobjekt für diesen Text zurückgegeben. Wenn Sie alle Zeichenfolgen durch diesen Kanonizierer übergeben, wissen Sie, dass gleichwertige Zeichenfolgen tatsächlich identische Objektreferenzen sind, d. H. Aliase

Die Aufzählungstypen in Java 5.0+ erzwingen, dass alle Instanzen eines bestimmten Aufzählungswerts dieselbe kanonische Instanz in einer VM verwenden, auch wenn der Wert serialisiert und deserialisiert wird. Aus diesem Grund können Sie if (day == Days.SUNDAY) in Java ungestraft verwenden, wenn Days ein Aufzählungstyp ist. Dies ist zwar für den eigenen Unterricht möglich, ist aber möglich. Lesen Sie Effective Java von Josh Bloch für Details und Ratschläge.

58
Dov Wasserman

Das Wort "kanonisch" ist nur ein Synonym für "Standard" oder "Normal". Es hat keine Java-spezifische Bedeutung.

24
Dónal

Ein gutes Beispiel für das Verständnis von "kanonischer Form/Darstellung" ist ein Blick auf die XML-Schema-Datentypdefinition von "boolean": 

  • die "lexikalische Darstellung" von boolean kann eine der folgenden sein: {true, false, 1, 0} während
  • die "kanonische Darstellung" kann nur eine von {true, false} sein.

Dies bedeutet im Wesentlichen das 

  • "true" und "1" werden dem kanonischen Repräsentanten zugeordnet. "true" und
  • "false" und "0" werden dem kanonischen Repräsentanten zugeordnet. "false"

siehe die w3 XML-Schema-Datentypdefinition für Boolean

24
Michael Marton

reduziert auf die einfachste und bedeutendste Form, ohne die Allgemeinheit zu verlieren

16
Jaime

Ein einfacher Weg, sich daran zu erinnern, ist die Art und Weise, wie "kanonisch" in theologischen Kreisen verwendet wird. Die kanonische Wahrheit ist die wahre Wahrheit. Wenn also zwei Personen sie finden, haben sie dieselbe Wahrheit gefunden. Dasselbe gilt für die kanonische Instanz. Wenn Sie glauben, dass Sie zwei davon gefunden haben (d. H. a.equals(b)), haben Sie wirklich nur eine (d. H. a == b). Gleichheit impliziert also Identität bei kanonischen Objekten.

Nun zum Vergleich. Sie haben jetzt die Wahl, a==b oder a.equals(b) zu verwenden, da sie im Falle einer kanonischen Instanz dieselbe Antwort liefern, aber a == b ist ein Vergleich der Referenz (die JVM kann zwei Zahlen extrem vergleichen Im Vergleich zu a.equals(b) ist dies ein Methodenaufruf, der mehr Overhead verursacht.

4
Chris Mawata

Ein anderes gutes Beispiel könnte sein: Sie haben eine Klasse, die die Verwendung von kartesischen (x, y, z), sphärischen (r, Theta, phi) und Zylinderkoordinaten (r, phi, z) unterstützt. Zum Zwecke der Festlegung der Gleichheit (gleiches Verfahren) möchten Sie wahrscheinlich alle Repräsentationen in eine "kanonische" Repräsentation Ihrer Wahl konvertieren, z. Kugelkoordinaten. (Oder vielleicht möchten Sie dies im Allgemeinen tun - d. H. Eine interne Darstellung verwenden.) Ich bin kein Experte, aber das kam mir als ein gutes konkretes Beispiel vor.

2

Die Fragen des OP über kanonische Form und darüber, wie die Leistung der equals-Methode verbessert werden kann, können beide durch die Erweiterung des in Effective Java bereitgestellten Beispiels beantwortet werden. 

Betrachten Sie die folgende Klasse:

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);
  }
}

Die equals-Methode in diesem Beispiel hat mit der String-Methode von equalsIgnoreCase zusätzliche Kosten verursacht. Wie im Text erwähnt

möglicherweise möchten Sie eine kanonische Form des Felds speichern, damit das Gleichheitszeichen Die Methode kann einen billigen exakten Vergleich mit kanonischen Formen durchführen, statt mit ein teurerer Nichtstandardvergleich.

Was meint Joshua Bloch, wenn er kanonische Form sagt? Nun, ich denke, Dónals prägnante Antwort ist sehr passend. Wir können das zugrunde liegende Feld String im Beispiel CaseInsensitiveString auf Standard-Weise speichern, möglicherweise in Großbuchstaben der String. Jetzt können Sie auf diese kanonische Form der Variablen CaseInsensitiveString, die Großbuchstabenvariante, verweisen und in Ihren Methoden equals und hashcode billige Auswertungen durchführen.

kanonische Darstellung bedeutet, den Charakter in einem anderen Stil anzuzeigen Wenn ich beispielsweise einen Buchstaben A schreibe, bedeutet dies, dass eine andere Person den Buchstaben A in einem anderen Stil schreiben kann :)

Dies entspricht dem OPTISCHEN ZEICHENERKENNUNGSFELD

0
SASIKALA

Eine kanonische Form bedeutet eine natürlich einzigartige Darstellung des Elements

0