Что означает термин «каноническая форма» или «каноническое представление» в Java?

Я часто слышал, как используется этот термин, но никогда не понимал его.

Что это означает, и может ли кто-нибудь привести несколько примеров / указать мне некоторые ссылки?

Обновлено: Спасибо всем за ответы. Можете ли вы также сказать мне, как каноническое представление полезно для производительности equals (), как указано в Эффективной Java?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
93
0
119 953
11
Перейти к ответу Данный вопрос помечен как решенный

Ответы 11

Слово «канонический» - всего лишь синоним «стандартного» или «обычного». Это не имеет никакого специфического для Java значения.

канонический имеет более богатое значение, чем стандартный или обычный IMO.

squid 12.11.2015 18:20
Ответ принят как подходящий

Википедия указывает на термин Канонизация.

A process for converting data that has more than one possible representation into a "standard" canonical representation. This can be done to compare different representations for equivalence, to count the number of distinct data structures, to improve the efficiency of various algorithms by eliminating repeated calculations, or to make it possible to impose a meaningful sorting order.

Пример Юникод имел для меня наибольший смысл:

Variable-length encodings in the Unicode standard, in particular UTF-8, have more than one possible encoding for most common characters. This makes string validation more complicated, since every possible encoding of each string character must be considered. A software implementation which does not consider all character encodings runs the risk of accepting strings considered invalid in the application design, which could cause bugs or allow attacks. The solution is to allow a single encoding for each character. Canonicalization is then the process of translating every string character to its single allowed encoding. An alternative is for software to determine whether a string is canonicalized, and then reject it if it is not. In this case, in a client/server context, the canonicalization would be the responsibility of the client.

Таким образом, стандартная форма представления данных. Из этой формы вы можете затем преобразовать в любое представление, которое вам может понадобиться.

Я считаю, что есть два связанных использования слова canonical: формы и экземпляры.

каноническая форма означает, что значения конкретного типа ресурса могут быть описаны или представлены несколькими способами, и один из этих способов выбран в качестве предпочтительной канонической формы. (Эта форма - канонизированный, как книги, вошедшие в Библию, а другие формы - нет.) Классическим примером канонической формы являются пути в иерархической файловой системе, где на один файл можно ссылаться разными способами. :

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

Классическим определением канонического представления этого файла будет последний путь. С локальными или относительными путями вы не можете глобально идентифицировать ресурс без контекстной информации. С помощью абсолютных путей вы можете идентифицировать ресурс, но не можете сказать, относятся ли два пути к одному и тому же объекту. С двумя или более путями, преобразованными в их канонические формы, вы можете сделать все вышеперечисленное, а также определить, являются ли два ресурса одинаковыми или нет, если это важно для вашего приложения (решить проблема сглаживания).

Обратите внимание, что каноническая форма ресурса не является качеством самой этой конкретной формы; для данного типа может быть несколько возможных канонических форм, таких как пути к файлам (скажем, лексикографически прежде всего возможные абсолютные пути). Одна форма просто выбрана в качестве канонической по определенной причине приложения или, возможно, произвольно, чтобы все говорили на одном языке.

Принуждение объектов к их канонические примеры - это та же основная идея, но вместо определения одного «лучшего» представления ресурса он произвольно выбирает один экземпляр класса экземпляров с тем же «содержанием», что и каноническая ссылка, а затем преобразует все ссылки в эквивалентные объекты для использования одного канонического экземпляра.

Это можно использовать как метод оптимизации времени и пространства. Если в приложении есть несколько экземпляров эквивалентных объектов, то, принудительно разрешив их все как один канонический экземпляр определенного значения, вы можете удалить все, кроме одного, каждого значения, сэкономив место и, возможно, время, поскольку теперь вы можете сравнивать эти значения с эталонным идентификатором (==) в отличие от эквивалентности объекта (метод equals()).

Классический пример оптимизации производительности с помощью канонических экземпляров - сворачивание строк с одинаковым содержимым. Вызов String.intern() для двух строк с одинаковой последовательностью символов гарантирует возврат одного и того же канонического объекта String для этого текста. Если вы пропустите все свои строки через этот каноникализатор, вы знаете, что эквивалентные строки на самом деле являются идентичными ссылками на объекты, то есть псевдонимами

Типы перечисления в Java 5.0+ заставляют все экземпляры определенного значения перечисления использовать один и тот же канонический экземпляр в виртуальной машине, даже если значение сериализовано и десериализовано. Вот почему вы можете безнаказанно использовать if (day == Days.SUNDAY) в java, если Days является типом перечисления. Сделать это для ваших собственных классов, конечно, можно, но будьте осторожны. Прочтите Эффективная Java Джоша Блоха для получения подробностей и советов.

сводится к простейшему и наиболее значительному виду без потери общности

каноническое представление означает просмотр персонажа в другом стиле например, если я напишу букву А, значит другой человек может написать букву А в другом стиле :)

Это в соответствии с ОПТИЧЕСКИМ ПОЛЕ РАСПОЗНАВАНИЯ ХАРАКТЕРА.

Другой хороший пример: у вас есть класс, который поддерживает использование декартовых (x, y, z), сферических (r, theta, phi) и цилиндрических координат (r, phi, z). В целях установления равенства (метод равенства) вы, вероятно, захотите преобразовать все представления в одно «каноническое» представление по вашему выбору, например сферические координаты. (Или, может быть, вы захотите сделать это вообще, то есть использовать одно внутреннее представление.) Я не эксперт, но мне это пришло в голову как, возможно, хороший конкретный пример.

Легкий способ запомнить это то, как «канонический» используется в теологических кругах, каноническая истина - это настоящая истина, поэтому, если двое людей находят ее, они нашли одну и ту же истину. То же и с каноническим экземпляром. Если вы думаете, что нашли два из них (например, a.equals(b)), у вас действительно только один (например, a == b). Таким образом, равенство подразумевает идентичность в случае канонического объекта.

Теперь для сравнения. Теперь у вас есть выбор использовать a==bили жеa.equals(b), поскольку они дадут тот же ответ в случае канонического экземпляра, но a == b - это сравнение ссылки (JVM может сравнивать два числа очень быстро, поскольку они всего два 32-битных шаблоны по сравнению с a.equals(b), который является вызовом метода и требует дополнительных затрат.

Хороший пример для понимания «канонической формы / представления» - это посмотреть на определение типа данных схемы XML «логическое»:

  • "лексическое представление" логического значения может быть одним из: {true, false, 1, 0}, тогда как
  • "каноническое представление" может быть только одним из {true, false}

Это, по сути, означает, что

  • "true" и "1" отображаются на канонический repr. "true" и
  • "false" и "0" отображаются на канонический репр. "false"

см. определение типа данных схемы XML w3 для логического

Каноническая форма означает естественно уникальное представление элемента.

На вопросы OP о каноническая форма и о том, как он может улучшить производительность метода equals, можно ответить, расширив пример, представленный в Эффективной Java.

Рассмотрим следующий класс:

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

Метод equals в этом примере добавил стоимость за счет использования метода StringequalsIgnoreCase. Как упоминалось в тексте

you may want to store a canonical form of the field so the equals method can do a cheap exact comparison on canonical forms rather than a more costly nonstandard comparison.

Что имеет в виду Джошуа Блох, когда говорит каноническая форма? Что ж, я думаю, что краткое отвечать Донала очень уместно. Мы можем сохранить базовое поле String в примере CaseInsensitiveString в виде стандарт, возможно, в форме верхнего регистра String. Теперь вы можете ссылаться на этот каноническая формаCaseInsensitiveString, его вариант в верхнем регистре, и выполнять дешевые оценки в ваших методах equals и hashcode.

Канонические данные в СУБД, графические данные;
Представьте себе «нормализацию» или «нормальную форму» данных в СУБД. Одни и те же данные существуют в разных таблицах, представлены уникальным идентификатором и отображены в разных таблицах. или
Подумайте об одной форме данных в базе данных Graph, которые представлены множеством троек.

Основное преимущество этого заключается в том, что Dml (манипулирование данными) становится более эффективным, поскольку вы можете вставлять (вставлять / обновлять) только одно значение вместо многих.

Другие вопросы по теме