Чому назви шаблонів не є константами?


211

Проблеми з гарнітурою самі по собі заплутані та складні, але крім того, ви повинні запам’ятати точні назви ваших карт. Це "utf8"? Або "utf-8"? А може "UTF-8"? Під час пошуку в Інтернеті зразків коду ви побачите все вищезазначене. Чому б просто не зробити їх названими константами і використовувати Charset.UTF8?


19
+1: Це також мене весь час клопотало. Ця ж історія продовжується MessageDigest#getInstance()до речі.
BalusC

2
Для справжньої відповіді вам потрібно буде запитати когось у Sun. Удачі в цьому :-)
Стівен C

1
Стівен С: Я вважаю, що це обговорювалося в загальнодоступному списку розсилки. -Не хтось у ВС.
Том Хотін - тайклін

1
дивіться це запитання
yegor256

Відповіді:


160

Проста відповідь на поставлене запитання полягає в тому, що наявні рядки діаграм відрізняються від платформи до платформи.

Однак є шість, які обов'язково повинні бути присутніми, тому константи могли бути зроблені для тих давно. Я не знаю, чому їх не було.

JDK 1.4 зробив чудову справу, представивши тип Charset. На даний момент вони більше не хотіли б надавати струнні константи, оскільки мета - отримати всіх, хто використовує екземпляри Charset. То чому б тоді не надати шість стандартних констант Charset? Я запитав у Мартіна Бухгольца, оскільки він, здається, сидить поруч зі мною, і він сказав, що насправді не було особливо великої причини, за винятком того, що в той час все ще було напівзапечене - занадто мало API JDK було оновлено прийняти Charset, а з тих, що були, перевантаження Charset зазвичай виконувались трохи гірше.

Сумно, що лише в JDK 1.6 вони нарешті закінчили оснащувати все перевантаженням Charset. І що ця ситуація на відсталому рівні ефективності все ще існує (причина, чому це неймовірно дивно, і я не можу це пояснити, але пов'язане з безпекою!).

Довга історія - просто визначте власні константи або скористайтеся класом Charsets Guava, до якого пов’язаний Тоні Поні (хоча ця бібліотека насправді ще не випущена).

Оновлення:StandardCharsets клас в JDK 7.


Просто цікаво, будь-яка ідея, коли буде реліз (альфа / бета / що завгодно) Guava? Домашня сторінка проекту дещо обмежена.
Jonik

Ніякої індички для мене, поки не вийде!
Кевін Бурліон

Причина, чому це неймовірно дивно, і я не можу пояснити це, але пов’язана із безпекою - ви можете створити змінну струну за допомогою користувацьких графічних діаграм, але вони могли бути зроблені навіть швидше, ніж рядки (що насправді шукає набір шаблону). Це упущення / нехтування способом String(byte bytes[], int offset, int length, Charset charset)реалізації. Насправді хіт продуктивності зовсім не тривіальний при створенні невеликого рядка з великого байта [].
bestsss

7
Нечесно! У вас є доступ до таких великих ресурсів. = (Я бачив ще одну відповідь, де ви одного разу сказали: "Так, тому я запитав Джоша [Блоха] про це ..."
kevinarpe

PrintStream не підтримує Charset
rofrol

102

Через два роки і StandardCharsets Java 7 тепер визначає константи для 6 стандартних діаграм.

Якщо ви застрягли на Java 5/6, ви можете використовувати константи « Шарсети Гуави» , як пропонують Кевін Бурліон і Джон Скіт.


29

Я заперечую, що ми можемо зробити набагато краще, ніж це ... чому не доступні безпосередньо гарантовані наявні шаблони? Charset.UTF8має бути посиланням на Charset, а не ім'я як рядок. Таким чином нам не довелося б поводитися UnsupportedEncodingExceptionвсюди.

Зауважте, я також думаю, що .NET обрав кращу стратегію, дефолт був повсюдно. Потім він перекрутився, просто назвавши властивість кодування "за замовчуванням операційної системи" Encoding.Default- що не є типовим для самого NET:

Назад до рейтингу про підтримку гардеробів Java - чому не існує конструктора для FileWriter/ FileReaderякий займає Charset? В основному це майже марні класи через це обмеження - вам майже завжди потрібен InputStreamReaderприблизно FileInputStreamабо еквівалент для виводу :(

Медсестра, медсестра - де моє ліки?

EDIT: Мені здається, що це насправді не відповіло на питання. Справжня відповідь, мабуть, або "ніхто про це не думав", або "хтось із причетних вважав це поганою ідеєю". Я настійно пропоную, щоб внутрішні класи утиліти, що надають імена чи графіки, уникали дублювання навколо бази даних коду ... Або ви могли просто використовувати той, який ми використовували в Google, коли ця відповідь була вперше написана . (Зверніть увагу, що на Java 7 ви просто використовуєте StandardCharsetsзамість цього.)


2
+1. Але як метод, а не поле, щоб дозволити ледачому завантаженню (добре, напевно, ви хочете UTF-8, але є кілька інших діаграм, і ви можете захотіти подібні засоби для них). На жаль, це здається не дуже популярним у тих, хто приймає рішення.
Том Хоутін - тайклін

Я був би досить задоволений методом, хоча сподіваюся, що охоче завантаження цих небагатьох діаграм не буде значною вартістю.
Джон Скіт

1
Ми на хрестовому поході, щоб зупинити нетерпляче завантаження класу. / Щойно здійснив пошук JDK для "UTF-8". Знайдено 270 збігів у 165 файлах. Хоча багато що в старих барахлах Apache (я вважаю, що сприяла моя команда).
Том Хотін - тайклін

1
@tackline: Я вважаю, що нетерпляче завантаження класів - це одна з тих речей, яка зростає з часом. Кілька занять тут, кілька класів там - кожен окремо звучить досить нешкідливо - могли б мати велике значення.
Джон Скіт

Остання ланка, до Guava Charsets, розірвана.
LarsH

28

На Java 1.7

import java.nio.charset.StandardCharsets

колишній: StandardCharsets.UTF_8 StandardCharsets.US_ASCII


5

Поточний стан API кодування залишає бажати кращого. Деякі частини Java 6 API не приймають Charsetзамість рядка (в logging, dom.ls, PrintStream, можуть бути і інші). Це не допомагає, що кодування мають різні канонічні назви для різних частин стандартної бібліотеки.

Я можу зрозуміти, як справи потрапили туди, де вони є; не впевнений, що у мене є геніальні ідеї щодо їх виправлення.


Як осторонь ...

Ви можете шукати назви для реалізації Java Sun 6 тут .

Для UTF-8, канонічні значення "UTF-8"для java.nioі "UTF8"для java.langі java.io. Єдині кодування, яким потрібна специфікація JRE для підтримки, є: US-ASCII; ISO-8859-1; UTF-8; UTF-16BE; UTF-16LE; UTF-16 .


2
Я не сприймаю PrintStream один, оскільки клас чітко говорить: "Клас PrintWriter слід використовувати в ситуаціях, які вимагають написання символів, а не байтів". (Що таке, як і всі ситуації ...)
Кевін Бурліон

2

Я давно визначив клас корисності з константами Charset UTF_8, ISO_8859_1 та US_ASCII.

Крім того , деякі давно ( від 2 років) , я зробив простий тест продуктивності між new String( byte[], Charset )і new String( byte[], String charset_name )і виявив , що остання реалізація ЗНАЧНО швидше. Якщо ви подивитесь під капот на вихідний код, то побачите, що вони дійсно йдуть зовсім іншим шляхом.

З цієї причини я включив утиліту до того ж класу

public static String stringFromByteArray (
    final byte[] array,
    final Charset charset
)
{
    try
    {
        return new String( array, charset.name( ) )
    }
    catch ( UnsupportedEncodingException ex )
    {
        // cannot happen
    }
}

Чому конструктор String (байт [], Charset) не робить те саме, мене б'є.


1
Не Charsetпотрібно реєструватись, тому може статися виняток. IIRC, в JDK7 відбулися деякі зміни, щоб зробити його швидшим для відомих хороших Charsetреалізацій (усунути зайву копію).
Том Хотін - тайклін
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.