Какой самый вводящий в заблуждение метод в Java Base API?

Недавно я пытался преобразовать строковый литерал в boolean, когда метод boolean Boolean.getBoolean(String name) выскочил из автозаполнения окно. Был также другой метод (boolean Boolean.parseBoolean(String s)), появившийся сразу после этого, что привело меня к поиску, чтобы выяснить, каковы различия между этими двумя, поскольку они оба, похоже, делали то же самое.

Оказывается, что то, что Boolean.getBoolean(String name) действительно делает, это проверить, существует ли свойство > (!) данного имени и если его значение true. Я думаю, что это очень вводит в заблуждение, поскольку я определенно не ожидаю, что метод boolean действительно вызывает вызов System.getProperty, и просто взглянув на подпись метода, он уверен, что выглядит (по крайней мере для меня), как будто он должен использоваться для анализа String как boolean. Конечно, javadoc четко заявляет, но я все же считаю, что метод имеет вводящее в заблуждение имя, и это не в нужном месте. Другие примитивные обертки типа, такие как Integer, также имеют аналогичный метод.

Кроме того, это не очень полезный метод, который должен принадлежать базовому API, так как я думаю, что это не очень похоже на нечто вроде -Darg=true. Может быть, это хороший вопрос для интервью на Java: "Что такое вывод Boolean.getBoolean("true")?". Я считаю, что более подходящее место для этих методов будет в классе System, например, getPropertyAsBoolean; но опять же, я по-прежнему считаю ненужным использовать эти методы в базовом API. Было бы разумно иметь их в чем-то вроде класса Properties, где очень часто делается этот тип преобразований.

Что вы думаете обо всем этом? Кроме того, если есть другой "неудобный" метод, о котором вы знаете, отправьте его.

N.B. Я знаю, что я могу использовать Boolean.valueOf или Boolean.parseBoolean для преобразования строкового литерала в boolean, но я просто хочу обсудить дизайн API.

Ответ 1

Метод URL equals() сравнивает IP-адреса, использует сетевое соединение и является блокировкой!

Из javadocs:

Два хоста считаются эквивалентными, если оба имени хоста могут быть решены в те же IP-адреса; иначе если имя хоста не может быть разрешено, имена хостов должны быть равны независимо от случая; или оба имена хостов равны нулю.

Так как для сравнения хостов требуется разрешение имен, эта операция является блокировка.

Примечание. Определенное поведение для равных значений известно быть несовместимым с виртуальным хостингом в HTTP.

Вместо этого используйте URI.

Ответ 2

Одна известная проблема с классом Calendar состоит в том, что месяцы нумеруются от 0 до 11 вместо 1 до 12. Очень легко сделать ошибку следующим образом:

Calendar cal = Calendar.getInstance();

// Set date to August 18, 2009? WRONG! Sets the date to September 18, 2009!
cal.set(2009, 8, 18);

Правильный способ сделать это - использовать константы в течение месяцев:

cal.set(2009, Calendar.AUGUST, 18);

Но метод делает слишком легко совершить ошибку при использовании нормальных чисел месяца от 1 до 12.

Я рассматриваю это как ошибку в дизайне класса Calendar.

Ответ 3

Просто получил этот здесь, касающийся методов add и remove List (при параметризации с помощью Integer). Например:

List<Integer> l = new ArrayList<Integer>();
l.add(20);
l.remove(20); // throws ArrayIndexOutOfBoundsException, because it will try to access index 20
l.remove(new Integer(20)); // this works   

Ответ 4

String.getBytes()

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

Ответ 5

Просто узнал о методах isInterrupted и interrupted класса Thread. Из javadoc:

static boolean interrupted()
// Tests whether the current thread has been interrupted.
boolean isInterrupted()
// Tests whether this thread has been interrupted.

Проблема заключается в том, что interrupted фактически очищает прерванный статус, помимо выполнения теста, а isInterrupted просто проверяет состояние.

Ответ 6

Вероятно, это не самый худший метод, но мне никогда не нравилось этот:

Предположим, что x - это список, который, как известно, содержит только строки. Следующий код можно использовать для удаления списка в новый выделенный массив String:

String[] y = x.toArray(new String[0]);

Передача массива String размера 0 в метод просто кажется сумасшедшим и неинтуитивным для меня.

Ответ 7

InputStream.read(byte [])

Не заполняет массив; вместо этого он считывает произвольное количество байтов и возвращает это число. Вы должны зациклиться. Отвратительно, потому что он работает правильно для небольших массивов большую часть времени. Я не думаю, что кто-то правильно это понимает в первый раз, когда они его используют.

Ответ 8

Некоторые redditor заметили, что String.substring приводит к утечкам памяти, потому что внутри он не копирует подстроку, а просто копирует указатель на целую строку + смещение + длину. Поэтому, если вы ожидаете, что вся строка будет собрана GC, вы будете ввернуты.

http://www.reddit.com/r/programming/comments/8ydvg/the_dangers_of_stringsubstring/c0au0gj

Ответ 9

моя проблема связана с методом подстроки String; каждый раз, когда я его использую, я должен написать слово "гамбургер" и "гамбургер".substring(4,8) = "побуждать" запомнить, как правильно его использовать.

Ответ 10

Ну, System.setOut() установит значение в final члена System!!!!

Ответ 11

Я никогда не понимал, почему API JDBC последовательно начинает подсчет с 1, тогда как остальные юниверсы Java (и C, С++, С#,...) начинаются с 0. Это относится к номерам столбцов, номерам параметров в подготовленном заявления и т.д.

Ответ 12

Я согласен. Мне всегда было неудобно с этими методами.

Я даже обнаружил ошибку в нашей базе кода, которая была вызвана кем-то, использующим Integer.getInteger() для синтаксического анализа строки, не понимая, что она ищет свойство.

К сожалению, конечно, API API не может быть удален из-за соображений обратной совместимости.

Ответ 13

Я не уверен, что кто-то все еще использует это, но сообщение об ошибке из DocumentBuilder.parse(), если что-то пойдет не так, (почти?) всегда "Содержимое не допускается в прологе". даже если реальная причина была чем-то другим.

Ответ 14

BigDecimal.setScale(int) сеттер, который возвращает BigDecimal hmmm

Ответ 15

Одно из моих любимых мотивов с Java - это тот факт, что сбой в Integer.parseInt( "SomeString" ) просто указывает, что произошла ошибка синтаксического анализа, не сказав нам, что такое "SomeString". Из-за этого иногда приходится выполнять множество отладки, чтобы узнать, что такое строка. Если ошибка mesage включала ошибочную строку, отслеживание проблемы было бы намного быстрее.

Ответ 16

Я бы не записал его под "Most Awkward", но java.security.MessageDigest.getInstance() дал мне некоторую путаницу.

Обычно я использую метод getInstance(), возвращающий Singleton.

Если метод возвращает новый экземпляр, я могу ожидать увидеть MessageDigestFactory.newInstance() или, по крайней мере, newInstance() в классе MessageDigest вместо метода getInstance().

Смотрите: MessageDigest.getInstance()

Из того, что я тестировал, MessageDigest.getInstance() возвращает новый экземпляр, каждый раз, когда он вызывается.

Ответ 17

java.util.Date.getDate() возвращено число, 1-31. getDayOfMonth() - это точный способ объяснить это, в то время как вы обычно пытались запомнить getTime().

Не могу дождаться, когда наступит время Джоды.