Декодирование URL: исключение UnsupportedEncodingException в Java

#java #encoding

#java #кодирование

Вопрос:

Что я понимаю из документации, что UnsupportedEncodingException только может быть выдано, если я указать неправильную кодировку в качестве второго параметра URLDecoder.расшифровать(строка, string) метод. Так ли это? Мне нужно знать случаи, когда это исключение может быть выдано.

В принципе, у меня есть этот сегмент кода в одной из моих функций:

 if (keyVal.length == 2) {
    try {
        value = URLDecoder.decode(
            keyVal[1],
            "UTF-8");
    } catch (UnsupportedEncodingException e) {
          // Will it ever be thrown?
    }
}
  

Поскольку я явно упоминаю «UTF-8», можно ли каким-либо образом создать это исключение? Нужно ли мне что-либо делать в блоке catch? Или, если мое понимание совершенно неверно, пожалуйста, дайте мне знать.

Ответ №1:

Этого не может произойти, если только в вашей JVM что-то фундаментально не сломано. Но я думаю, вам следует написать это как:

 try {
    value = URLDecoder.decode(keyVal[1], "UTF-8");
} catch (UnsupportedEncodingException e) {
    throw new AssertionError("UTF-8 is unknown");
    // or 'throw new AssertionError("Impossible things are happening today. "  
    //                              "Consider buying a lottery ticket!!");'
}
  

Стоимость выполнения этого составляет несколько байтов кода, который «никогда» не будет выполнен, и один строковый литерал, который никогда не будет использоваться. Это небольшая цена за защиту от возможности того, что вы, возможно, неправильно прочитали / поняли javadocs (в данном случае вы этого не сделали …) или что спецификации могут измениться (в этом случае они не будут …)

Комментарии:

1. Каковы некоторые практические вероятные примеры того, что JVM будет сломана?

2. @Pacerier — я не могу придумать ни одного. Вероятно, вам потребуется изменить «rt.jar «файл (или хуже), чтобы сломать это. Так что это теоретически возможно … но это не то, с чем вы, вероятно, когда-либо столкнетесь, если вы не создаете / используете экспериментальную JVM.

3. Есть ли какая-либо причина, по которой проверяется это исключение?

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

5. Другая проблема заключается в том, что это только «UTF-8», где есть гарантия, что исключение не может быть выдано. Для других имен кодировок… исключение возможно, и проверка исключения является разумным решением. Возможно, решением было бы добавить URLDecoder.decodeUTF8( метод, который вообще не выдавал исключение.

Ответ №2:

Это из-за странного выбора, который нужно сделать UnsupportedEncodingException проверено. Нет, оно не будет выдано.

Обычно я делаю следующим образом:

 } catch (UnsupportedEncodingException e) {
  throw new AssertionError("UTF-8 not supported");
}
  

Ответ №3:

В вашем особом случае — нет, оно не будет выдано. Если только вы не выполняете свой код в среде выполнения Java, которая не поддерживает «UTF-8».

Комментарии:

1. Предполагается, что такая среда выполнения не существует — по крайней мере, в JDK 1.6 UTF-8 является стандартной кодировкой. download.oracle.com/javase/6/docs/api/java/nio/charset /…

2. @Mat — Я тоже в это верю, но.. Oracle не единственный поставщик сред выполнения Java. В спецификации языка Java не упоминаются какие-либо кодировки, которые должны поддерживаться (за исключением: UTF-16, который является указанной кодировкой для char )

3. Вау, спасибо. Я думал, что это так, и что javadoc, похоже, подразумевает это, но вы правы, этого нет в JLS.

4. @Andreas_D: Хотя JLS не определяет кодировки, javadocs, связанные Mat, также являются спецификацией и являются нормативными. Таким образом, любые сертифицированные реализации Java должны поддерживать UTF-8 в предоставленной реализации Java core API.

5. javadocs являются нормативными? У вас есть ссылка на это утверждение? Честно говоря, я не верю, что нужно внедрять JLS и все детали javaDoc (какой версии, кстати?), чтобы получить сертификат.

Ответ №4:

Чтобы ответить на старый вопрос для новых читателей:

В Java 11 теперь есть URLDecoder.decode(String, Charset); который не выдает. Таким образом, вам вообще не нужно использовать блок try-catch. Просто сделайте:

 URLDecoder.decode(keyVal[1], StandardCharsets.UTF_8);