Стоит ли создавать пустую строковую константу?

У меня есть коллега, который клянется

//in a singleton "Constants" class
public static final String EMPTY_STRING = "";

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

if (Constants.EMPTY_STRING.equals(otherString)) {
    ...
}

вместо

if ("".equals(otherString)) {
    ...
}

Я говорю это

  1. не стоит - это не экономит место в пуле кучи / стека / строк,
  2. уродливый
  3. злоупотребление классом констант.

Кто здесь идиот?

сотрудник? Как орочь корову? знак равно

Erik Forbes 18.10.2008 07:44

К вашему сведению: в .NET есть String.Empty в качестве основного API. Некоторые люди клянутся этим. Я всегда использую "", поскольку считаю его таким же фундаментальным, как 0, и его легче читать - поэтому я против любой попытки маскарада;) В любом случае, я верю, что в C# /. NET было время, когда строки не интернировались, но я Я не уверен. В любом случае, в наши дни это уже не проблема ни для Java, ни для C#.

user166390 05.12.2010 12:40

Похоже на дубликат stackoverflow.com/q/4095501, но с дополнительным условием, что ваш коллега хочет заново изобрести колесо.

Dawood ibn Kareem 03.05.2018 02:09
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
29
3
26 981
18
Перейти к ответу Данный вопрос помечен как решенный

Ответы 18

Я предпочитаю видеть EMPTY_STRING.

Это делает его английским. "" .equals "читает" иначе, чем EMPTY_STRING.equals.

нет никаких причин для уменьшения этого мода.

Dustin Getz 18.10.2008 02:38

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

binki 20.05.2014 17:13
  1. да - пользы от этого нет.
  2. Я уверен, зависит от того, к чему вы привыкли.
  3. Нет, это просто константа, а не злоупотребление.

Мне не нравится ни один из вариантов. Почему не if (otherString.length() == 0)

Обновлено: я на самом деле всегда кодирую

if (otherString == null || otherString.length() == 0)

Потому что, если otherString имеет значение null, это вызывает исключение

Bill K 18.10.2008 02:07

Теперь должно быть 0. Я озадачен, почему я не увидел ответа Дугласа Белки. Должно быть время.

David G 18.10.2008 02:12

Также существует статический метод служебной программы Jakarta String для определения того, является ли строка пустой, то есть пустой или пустой.

bpapa 18.10.2008 02:57

StringUtils от Apache Common гораздо более полезен в этом отношении. Имеет массу хороших статических методов.

MetroidFan2002 18.10.2008 07:49
Ответ принят как подходящий

Строковые литералы интернированы по умолчанию, поэтому независимо от того, сколько раз вы ссылаетесь на "" в коде, будет только один пустой объект String. Я не вижу никакой пользы в объявлении EMPTY_STRING. В противном случае вы также можете объявить ONE, TWO, THREE, FOUR и т. д. Для целочисленных литералов.

Конечно, если вы захотите позже изменить значение EMPTY_STRING, удобно разместить его в одном месте;)

Они всегда интернированы или просто так? Гарантировано ли вам, что все пустые строки будут равны всем другим пустым строкам, даже вне границ классов и пакетов?

Paul Tomblin 18.10.2008 02:11

Вся пустая строка литералы. Вы можете создать другие отдельные объекты String, которые также будут пустыми.

Dan Dyer 18.10.2008 02:12

Все литералы и значения «постоянных выражений» интернированы. См. Спецификацию JVM: java.sun.com/docs/books/jvms/second_edition/html/…

James Schek 18.10.2008 04:23

Кроме того, если вы когда-нибудь увидите в коде EMPTY_STRING, вам действительно нужно проверить, что это такое. Это могло быть "", "" или даже "пусто". Это добавляет (ненужную) когнитивную нагрузку

Entreco 11.09.2020 10:34

Зачем вам глобальная переменная в Java? Джеймс Гослинг действительно пытался избавиться от них; не возвращай их, пожалуйста.

Либо

0 == possiblyEmptyString.length()

или же

possiblyEmptyString.isEmpty() // Java 6 only

столь же ясны.

кроме случая, когда возможно, что пустая строка пуста, тогда вы получите NPE

tuler 26.11.2009 22:49

Я думаю, что в определенных сценариях также имеет смысл обрезать значение String при проверке длины, что-то вроде этого: 0 == возможноEmptyString.trim (). Length () Я думаю, что в некоторых сценариях это имеет смысл, потому что если для по любой причине ваша переменная possibleEmptyString имеет это значение "", lenght вернет 3. Конечно, я рассматриваю возможность использования Java 1.5, потому что, как вы заявили, Java 6 имеет метод isEmtpy ().

Fernando Moyano 25.02.2012 18:43

По иронии судьбы весь смысл констант в том, чтобы сделать их легко изменяемыми. Поэтому, если ваш коллега не планирует переопределить EMPTY_STRING как нечто иное, чем пустая строка - что было бы действительно глупо, - приведение подлинной фиксированной конструкции, такой как "", к константе - это плохо.

Как говорит Дэн Дайер, это похоже на определение константы ONE равной 1: это совершенно бессмысленно и было бы совершенно запутанным - потенциально рискованным - если бы кто-то переопределил его.

Тот же аргумент время от времени возникает в .NET (где уже есть статическое поле string.Empty только для чтения). Это дело вкуса, но лично я нахожу "" менее навязчивым.

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

tvanfosson 18.10.2008 02:47

Хм, правила правильные, но их понимают в другом смысле! Давайте посмотрим на причину, сначала все ссылки на объекты в java проверяются с помощью equals (). Раньше на некоторых языках это делалось с помощью оператора '==', если кто-то случайно использовал '=' вместо '==', катастрофа. Теперь вопрос о магических числах / константах, для компьютера все константы / числа похожи. Вместо int ONE = 1, конечно, можно использовать 1, но будет ли это верно для double PI = 3.141 ...? Что произойдет, если позже кто-то попытается изменить точность.

Если бы мы составили контрольный список, какое правило соответствовало бы общему руководству, не так ли? Все, что я хочу сказать, это то, что правила призваны помогать, мы определенно можем изменить правила, только если знаем их очень хорошо. Здравый смысл преобладает. Как предложил мой друг, программные константы, такие как 0/1, которые обозначают условия выхода, могут быть жестко закодированы, и, следовательно, принцип магического числа не применяется. Но для тех, кто участвует в логических проверках / правилах, лучше сохранить их как настраиваемые константы.

Для подобных ситуаций мы просто делаем следующее:

public class StaticUtils
{
    public static boolean empty(CharSequence cs)
    {
        return cs == null || cs.length() == 0;
    }

    public static boolean has(CharSequence cs)
    {
        return !empty(cs);
    }
}

Тогда просто import static StaticUtils.*

Строка null - это не то же самое, что пустая строка.

Laurent Pireyn 20.11.2017 23:31

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

FWIW, C# имеет строку статического свойства. Пусто только для этой цели, и я считаю, что это значительно улучшает читаемость кода.

Если вы не программируете моноширинный шрифт, вы делаете это неправильно. Если да, то есть очевидная разница между "" и "".

David Thornley 19.10.2009 18:03

Однако при быстром сканировании нет такой очевидной разницы между "" и "'".

JUST MY correct OPINION 05.12.2010 12:37

Один случай, когда имеет смысл иметь константу со значением пустой строки, - это когда имя фиксирует семантику значения. Например:

if (Constants.FORM_FIELD_NOT_SET.equals(form.getField("foobar"))) {
    ...
}

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

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

Произвольная строка проверяется различными методами. (несколько итераций)

Результаты показывают, что isEmpty () быстрее и более читабельна; Если isEmpty () недоступен, хорошей альтернативой является length ().

Использование константы, вероятно, не стоит.

"".equals(someString())      :24735 ms
t != null && t.equals("")    :23363 ms
t != null && t.equals(EMPTY) :22561 ms
EMPTY.equals(someString())   :22159 ms
t != null && t.length() == 0 :18388 ms
t != null && t.isEmpty()     :18375 ms
someString().length() == 0   :18171 ms

В этом сценарии;

"IAmNotHardCoded".equals(someString())

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

Customer.FIELD_SHOE_SIZE //"SHOE_SIZE"

Может считаться подходящим местом, где как;

CommonConstants.I__AM__A__LAZY__PROGRAMMER // true

не является.

Для BigIntegers и подобных вещей я обычно определяю конечную статику локально; нравиться:

private final static BigDecimal ZERO = new BigDecimal(0);
private final static BigDecimal B100 = new BigDecimal("100.00");

Меня это беспокоит, и было бы неплохо добавить немного сахара для BigInts и BigDecimals ...

Хе-хе, забавная штука: После компиляции вы не увидите разницы (в байтовом коде) между "static final" и строковым литералом, поскольку Java-компилятор всегда встраивает "static final String" в целевой класс. Просто измените свою пустую строку на что-нибудь узнаваемое (например, LGPL-текст) и посмотрите на получившийся * .class файл кода, который ссылается на эту константу. Вы найдете свой текст скопированным в этот файл класса.

Что касается вопроса, я обычно рекомендую использовать служебную функцию, когда вы действительно проверяете «отсутствие полезного значения», а не, в частности, пустую строку. В общем, я обычно использую:

import org.apache.commons.lang.StringUtils;

// Check if a String is whitespace, empty ("") or null.
StringUtils.isBlank(mystr); 
// Check if a String is empty ("") or null.
StringUtils.isEmpty(mystr); 

Идея состоит в том, что два вышеупомянутых:

  • Проверьте различные другие случаи, включая нулевую безопасность и (что более важно)
  • Сообщает то, что вы пытаетесь проверить, а не то, как это тестировать.

Почему предпочтительнее использовать String.Empty в C# и, следовательно, общедоступную константу на других языках, заключается в том, что константы статичны, поэтому занимают только один экземпляр в памяти.

Каждый раз, когда вы делаете что-то вроде этого: -

stringVariable = "";

вы создаете новый экземпляр нулевой строки и указываете на него с помощью stringVariable.

Таким образом, каждый раз, когда вы присваиваете "" переменной (указателю), эта "" нулевая строка является новым экземпляром строки до тех пор, пока не перестанет быть присвоенным ей указателем.

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

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

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

const String EMPTY_STRING = "";
String variable1 = EMPTY_STRING;
String variable2 = EMPTY_STRING;
String variable3 = EMPTY_STRING;
String variable4 = EMPTY_STRING;
String variable5 = EMPTY_STRING;

Вы создали 5 указателей на строку, но только 1 строку

скорее, чем: -

String variable1 = "";
String variable2 = "";
String variable3 = "";
String variable4 = "";
String variable5 = "";

Вы создали 5 указателей на строки и 5 отдельных нулевых строк.

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

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

Кроме того, он менее подвержен ошибкам, так как оба элемента компилируются, но вы можете пропустить случайно добавленное пространство, что может привести к ложным ошибкам времени выполнения, например условной логике, такой как: -

myvariable = " ";
While (myVariable == ""){
 ...
}

Код внутри блока while недоступен, поскольку myVariable не удовлетворяет условию на первой итерации. Ошибка инициализации с "" вместо "" легко пропустить, тогда как: -

myvariable = EMPTY_STRING;
While (myVariable == EMPTY_STRING){
 ...
}

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

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

public static class StringConstants{
    public static String Empty = "";
    public static String EMail = "mailto:%s";
    public static String http = "http://%s";
    public static String https = "https://%s";
    public static String LogEntry = "TimeStamp:%tYmdHMSL | LogLevel:%s| Type:%s | Message: '%s'";

}

String myVariable = StringConstants.Empty;

Вы даже можете расширить собственный объект String, в зависимости от вашего языка.

Но интернирование строк… «но в тысячах строк кода в десятках классов это ненужная трата памяти и использование процессора, создание еще одной переменной с нулевой строкой» - вероятно, меньше циклов компилятора используется для интернирования пустой строки в компиляторе Java, чем для расширить константу. Но я не проверял: а вы?

binki 20.05.2014 17:19

Вопрос не в C#. И: «Он сказал указатель!». ;)

Gerold Broser 03.07.2016 15:23

Дэвид Арно заявляет: -

Ironically the whole point of constants is to make them easily changeable

Это просто неправда. Вся суть констант заключается в повторном использовании одного и того же значения для большей читабельности.

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

С самого начала программирования константы использовались, чтобы превратить такие вещи, как загадочные шестнадцатеричные значения, такие как 0xff6d8da412, в нечто удобочитаемое без намерения Когда-либо изменять значения.

const int MODE_READ       = 0x000000FF;
const int MODE_EXECUTE    = 0x00FF0000;
const int MODE_WRITE      = 0x0000FF00;
const int MODE_READ_WRITE = 0x0000FFFF;

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

Greg Brown 24.10.2012 16:54

Если вы все время хотите хранить «пустые» строки в столбце строки, допускающей значение NULL, в oracle, вам придется изменить определение EMPTY_STRING на что-то другое, кроме «»! (Я вспоминаю из прошлого раза, когда меня заставляли использовать Oracle, что он не знает разницы между пустой строкой и пустой строкой).

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

Или просто укажите его как string.IsNullOrEmpty (otherString)

Это вопрос Java, а не C#

anon 15.10.2020 12:30

Вы имеете в виду otherString.equals("") или предлагаете использовать такую ​​библиотеку, как Guava или Apache Commons?

NeatNerd 15.10.2020 12:40

Пожалуйста, добавьте какое-нибудь пояснение - на этот вопрос уже есть много ответов - чем ваш ответ отличается, почему это лучшее решение?

Oozeerally 15.10.2020 13:45

Другие вопросы по теме