Подтвердить что ты не робот

Вызов равенства на строковый литерал

Я просто немного убирал свой код и был этот кусок:

String saving = getValue();
if(saving != null && saving.equals("true")){
   // do something
}

Затем я подумал о том, чтобы сделать это наоборот, чтобы избавиться от проверки на null:

if("true".equals(saving)){
   // do something
}

Это определенно работает, но безопасно для этого? Я имею в виду, что строковые литералы хранятся в общем пуле, а строковый объект, создаваемый new, находится в куче. Но строки в постоянном пуле также являются объектами, правильно?

Но все же это не похоже на правильную вещь, хотя это делает код короче.

4b9b3361

Ответ 1

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

Вы упомянули использование new для строк. Многие инструменты анализа статического кода Java рекомендуют всегда использовать литералы над new String("foo");.

Edit:

Если бы вы хотели, вы могли бы просто использовать:   

if (Boolean.valueOf(saving)) {
    ...
}

В соответствии с docs передача null вернет false.

Ответ 2

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

Я думаю, что этот механизм глуп.

Если у вас есть null, вы должны знать, как только это произойдет - скрыть его, просто отложит его открытие. Если null не является исключением, замените его на что-то еще.

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

В заключение - NullPointerException - ваш друг. Вы должны использовать его, чтобы находить ошибки в коде. Это очень простой в использовании пустой объект, такой как Collections.emptySet(), как только вы определили, что null не является исключением.

Использование техники Йоды по привычке неизбежно скрывает ошибки, которые вы не хотите скрывать. Не, используя это, вы обнаружите ошибки намного раньше. Для меня это достаточный аргумент, чтобы не использовать его - когда-либо.

Для меня - используя

if(saving != null && saving.equals("true")){

означает, что я действительно хочу разрешить savings быть null, и это приемлемая ситуация - используя

if("true".equals(saving)){

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

Ответ 3

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

Но иногда использование условия yoda делает код более "понятным" -> вам не нужно ставить дополнительную проверку нулевого значения перед ним, и он эффективно дифференцирует блок кода из случая, когда null категорически запрещен.

Ответ 4

Я не согласен с некоторыми ответами. Иногда вы do хотите знать, есть ли ваша переменная null. Это может быть признаком того, что что-то плохое происходит в вашем коде, и вы можете пересмотреть свою логику.

Мне не нравится делать if("someString".equals(myString));, потому что я do хочет знать, есть ли myString null и, возможно, обработать его или изменить мою логику, чтобы предотвратить подобные ситуации.

Представьте, что у вас есть массив объектов, который был просчитан из-за некоторой ошибки:

myStrings = {..., ..., null, null, ...};

Затем вы хотите выполнить некоторые операции над объектами массива, и у вас будет:

if("myString".equals(myObjArray[i])) { ... } 

Вы не получите NullPointerException, и вы подумаете, что выполнили операцию над всеми объектами в массиве. И вы никогда не узнаете, что вы просчитали его, потому что вы "скрыли" исключение. Если вы это сделали:

if(myObjArray[i].equals("myString")) { ... } 

Вы получите NPE, и вы узнаете, что что-то не так в массиве.. и вы можете исправить это или обработать его по-другому.

Ответ 5

if("true".equals(saving)){
   // do something
}

Это очень безопасная и эффективная практика. Строка "true" никогда не будет равна нулю. Таким образом, вы никогда не сравните свою строку со значением null. Этот фрагмент кода отлично подходит

Ответ 6

Формат помещения литерала сначала избегает потенциального NPE и всегда будет ложным для "literal".equals(null).

Это потому, что выражение "буквальное" всегда оценивает объект String (и поэтому никогда не является нулевым), а String.equals(obj) проверяет, является ли другой объект нулевым (через asinstanceof). Объект - объект - не нужно беспокоиться о "куче".

Хорошая практика иметь нулевую охрану в эквивалентную реализацию, поскольку null.equals(null) недопустимо: "Метод equals реализует эквивалентность отношение к ненулевым объектным ссылкам"

Вот String.equals источник (для OpenJDK):

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        // ..
    }
    return false;
}

Ответ 7

Извините, но я не могу согласиться с этой проблемой.

Если вы используете константу сначала, вы поддерживаете структуры, которые создают ошибки программирования вуали. И нужно только генерировать код либо

  • добавить функциональность,
  • исправить ошибку программирования
  • или пытаться поддерживать структуры, чтобы избежать ошибок программирования (например, шаблоны проектирования).

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

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

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

Понимаете, этот вопрос больше связан с тем, чтобы избежать null, чем принять его, чтобы покорить ваш код.

Ответ 8

Не только безопасно, но также является предпочтительным способом решения этой проблемы.