Що означає термін «канонічна форма» або «канонічне подання» на Java?


90

Я часто чув, як використовується цей термін, але ніколи насправді його не розумів.

Що це означає, і чи може хтось навести деякі приклади / вказати мені на деякі посилання?

EDIT: Дякуємо усім за відповіді. Чи можете ви також сказати мені, як канонічне подання корисне у рівності (), як зазначено в Effective Java?

Відповіді:


56

Вікіпедія вказує на термін канонізація .

Процес перетворення даних, що має більше одного можливого подання, у "стандартне" канонічне подання. Це можна зробити для порівняння різних подань щодо еквівалентності, для підрахунку кількості різних структур даних, для підвищення ефективності різних алгоритмів шляхом усунення повторних обчислень або для того, щоб можна було накласти значущий порядок сортування.

Приклад Unicode мав для мене найбільший сенс:

Кодування із змінною довжиною у стандарті Unicode, зокрема UTF-8, мають більше одного можливого кодування для найбільш поширених символів. Це ускладнює перевірку рядків, оскільки слід враховувати кожне можливе кодування кожного символу рядка. Впровадження програмного забезпечення, яке не враховує всі кодування символів, ризикує прийняти рядки, які вважаються недійсними в дизайні програми, що може спричинити помилки або дозволити атаки. Рішення полягає в тому, щоб дозволити єдине кодування для кожного символу. Тоді канонізація - це процес перекладу кожного рядкового символу в його єдине дозволене кодування. Альтернативою є програмне забезпечення, яке визначає, чи рядок канонізовано, а потім відхиляє його, якщо ні. У цьому випадку, в контексті клієнт / сервер, канонізація буде відповідальністю клієнта.

Таким чином, стандартна форма подання даних. За допомогою цієї форми ви можете перетворити на будь-яке представлення, яке вам може знадобитися.


64

Я вважаю, що канонічне використання пов’язане між собою двома способами: форми та екземпляри.

А канонічна форма , означає , що значення певного типу ресурсу можуть бути описані або представлені кілька способами, і один з цих способів вибираються в якості сприяння канонічної форми. (Ця форма канонізована , як книги, що потрапили до Біблії, а інші форми - ні.) Класичним прикладом канонічної форми є шляхи в ієрархічній файловій системі, де на один файл можна посилатися різними способами. :

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 Джоша Блоха, щоб отримати докладні відомості та поради.


31

Хороший приклад для розуміння "канонічної форми / подання" - це ознайомлення з визначенням типу логічної схеми схеми XML:

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

Це, по суті, означає це

  • "true"і "1"потрапити на карту до канонічного видання. "true"і
  • "false"і "0"потрапити на карту до канонічного видання."false"

див. визначення типу даних схеми w3 XML для логічного значення


28

Слово "канонічний" є лише синонімом "стандартного" або "звичайного". Він не має жодного специфічного для Java значення.


3
канонічне має більш багате значення, ніж стандартне або звичайне ІМО.
кальмар

20

зводиться до найпростішої та найзначнішої форми, не втрачаючи загальності


5

Легкий спосіб запам’ятати це спосіб, яким у канонічних колах використовується „канонічна”, канонічна істина є справжньою істиною, тому якщо двоє людей знаходять її, вони знаходять ту саму істину. Те саме з канонічною інстанцією. Якщо ви думаєте, що знайшли два з них (тобто a.equals(b)), ви насправді маєте лише одного (тобто a == b). Отже, рівність передбачає ідентичність у випадку канонічного об'єкта.

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


2

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


0

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

Це відповідно до ОПТИЧНОГО РОЗПІЗНАВАННЯ ХАРАКТЕРІВ



0

Питання ОП щодо канонічної форми та того, як це може покращити ефективністьequals методу, можна відповісти, розширивши приклад, наведений у Effective 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Метод в цьому прикладі додав вартість, використовуючи String«и equalsIgnoreCaseметод. Як зазначалося в тексті

можливо, ви захочете зберегти канонічну форму поля, щоб метод equals міг зробити дешеве точне порівняння канонічних форм, а не більш дороге нестандартне порівняння.

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


0

Канонічні дані в СУБД, графічні дані;
Подумайте, як "Нормалізація" або "Звичайна форма" даних у СУБД. Ті самі дані існують у різних таблицях, представлених унікальним ідентифікатором та зіставлених у різних таблицях.
або
Подумайте про одну форму даних у графічній базі даних, яка представлена ​​у багатьох потрійних числах.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.