Почему статические переменные считаются злыми?

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

Я считаю, что статические переменные более удобны в использовании. И я полагаю, что они тоже эффективны (пожалуйста, поправьте меня, если я ошибаюсь), потому что, если мне пришлось сделать 10 000 вызовов функции внутри classа, я был бы рад сделать статический статический метод и использовать простой Class.methodCall() на нем вместо загромождения памяти с 10 000 экземпляров classа, не так ли?

Кроме того, статика уменьшает взаимозависимости на других частях кода. Они могут выступать в качестве прекрасных государственных держателей. Добавляя к этому, я обнаружил, что статика широко применяется на некоторых языках, таких как Smalltalk и Scala . Так почему же это угнетение для статики распространено среди программистов (особенно в мире Java)?

PS: Пожалуйста, поправьте меня, если мои предположения о статике неверны.

Статические переменные представляют собой глобальное состояние. Трудно рассуждать и трудно проверить: если я создаю новый экземпляр объекта, я могу рассуждать о его новом состоянии в тестах. Если я использую код, который использует статические переменные, он может быть в любом состоянии – и что-то может его изменить.

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

Его не очень объектно ориентированная: одна из причин, по которой статика может считаться «злой» некоторыми людьми, противоречит объектно-ориентированной парадигме . В частности, это нарушает принцип, что данные инкапсулируются в объекты (которые могут быть расширены, скрытие информации и т. Д.). Статика в том, как вы описываете их использование, по сути, должна использовать их как глобальную переменную, чтобы избежать проблем с такими областями. Однако глобальные переменные являются одной из определяющих характеристик процедурной или императивной парадигмы программирования, а не характеристикой «хорошего» объектно-ориентированного кода. Это не значит, что процедурная парадигма плоха, но у меня создается впечатление, что ваш руководитель ожидает, что вы напишете «хороший объектно-ориентированный код», и вы действительно хотите написать «хороший процедурный код».

Есть много gotchyas в Java, когда вы начинаете использовать статику, которая не всегда сразу очевидна. Например, если у вас есть две копии вашей программы, запущенной на той же виртуальной машине, будут ли они изменять значение статической переменной и беспорядок в состоянии друг друга? Или что происходит, когда вы расширяете class, можете ли вы переопределить статический член? У вашей виртуальной машины заканчивается память, потому что у вас есть безумные цифры статики, и эта память не может быть исправлена ​​для других необходимых экземпляров?

Object Lifetime: Кроме того, статика имеет срок службы, соответствующий всей среде выполнения программы. Это означает, что даже после того, как вы закончите использовать свой class, память из всех этих статических переменных не может быть собрана в мусор. Если, например, вы сделали свои переменные нестатичными, а в своей основной () функции вы сделали один экземпляр вашего classа, а затем попросили ваш class выполнить определенную функцию 10 000 раз, после того, как эти 10 000 вызовов были выполнены , и вы удаляете свои ссылки на один экземпляр, все ваши статические переменные могут быть собраны и повторно использованы для сбора мусора.

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

Другие параметры. Если эффективность является вашей основной задачей, могут быть другие более эффективные способы решения проблемы скорости, чем рассматривать только преимущество вызова, которое обычно происходит быстрее, чем создание. Подумайте, нужны ли переходные или изменчивые модификаторы в любом месте. Чтобы сохранить возможность быть встроенным, метод может быть помечен как final, а не static. Параметры метода и другие переменные могут быть отмечены как final, чтобы разрешить определенные оптимизаторы компилятора на основе предположений о том, что может изменить эти переменные. Объект экземпляра может повторно использоваться несколько раз, а не каждый раз создавать новый экземпляр. Могут быть переключатели оптимизации компилятора, которые должны быть включены для приложения в целом. Возможно, дизайн должен быть настроен так, чтобы 10 000 прогонов могли быть многопоточными и использовать многопроцессорные ядра. Если portablity не вызывает беспокойства, возможно, родной метод даст вам лучшую скорость, чем ваша статика.

Если по какой-то причине вы не хотите, чтобы несколько копий объекта, шаблон дизайна singleton , имеет преимущества перед статическими объектами, такие как безопасность streamов (предполагая, что ваш синглтон закодирован хорошо), позволяя ленивую инициализацию, гарантируя, что объект был правильно инициализируется, когда он используется, подclassификация, преимущества в тестировании и рефакторинг вашего кода, не говоря уже о том, что если вы в какой-то момент передумаете о том, что хотите только одного экземпляра объекта, намного проще удалить код, чтобы предотвратить дублирование экземпляров чем рефакторинг всего вашего статического кода переменной для использования переменных экземпляра. Я должен был сделать это раньше, это не забавно, и вам в итоге нужно редактировать намного больше classов, что увеличивает риск введения новых ошибок … так лучше, чтобы все было правильно «правильно» в первый раз, даже если кажется, что у него есть свои недостатки. Для меня требуется повторная работа, если вы решите, что вам нужно несколько копий что-то, вероятно, одна из самых убедительных причин использовать статику как можно реже. И, таким образом, я бы тоже не согласился с вашим утверждением, что статика уменьшает межзависимости, я думаю, что вы получите код, который будет более скомбинирован, если у вас будет много статистики, к которой можно напрямую обращаться, а не к объекту, который «знает, как это сделать» что-то “на себе.

Зло – субъективный термин.

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

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

Это две основные проблемы, которые у меня есть.

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

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

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

Как люди Весны, которые щедро объявляют глобальные состояния в xml и как-то думают, что они превосходят.

@Jon Skeet, if I create a new instance of an object теперь у вас есть две причины рассуждать – состояние внутри объекта и состояние среды, в которой размещен объект.

Существуют две основные проблемы со статическими переменными:

  • Безопасность streamов – статические ресурсы по определению не являются streamобезопасными
  • Кодекс Implicity – вы не знаете, когда статические переменные создаются и будет ли он создан для создания другой статической переменной

Если вы используете ключевое слово «статическое» без ключевого слова «final», это должно быть сигналом для тщательного рассмотрения вашего дизайна. Даже наличие «финала» не является бесплатным пропуском, поскольку изменчивый статический конечный объект может быть столь же опасным.

Я бы оценил где-то около 85% времени, когда вижу «статический» без «финала», это НЕПРАВИЛЬНО. Часто я обнаруживаю странные обходные пути, чтобы маскировать или скрывать эти проблемы.

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

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

Если вы хотите получить более подробную информацию, пожалуйста, прочитайте …

Почему не использовать статику?

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

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

Если вы используете статику, невозможно выполнить замену реализации classа, чтобы проверить компоненты более высокого уровня. Например, представьте себе статический CustomerDAO, который возвращает объекты Customer, которые он загружает из базы данных. Теперь у меня есть class CustomerFilter, которому нужно получить доступ к некоторым объектам Customer. Если CustomerDAO является статическим, я не могу написать тест для CustomerFilter без предварительной инициализации моей базы данных и заполнения полезной информации.

И наseleniumие и инициализация базы данных занимают много времени. И, по моему опыту, ваша база инициализации базы данных будет меняться со временем, то есть данные будут морфироваться, а тесты могут нарушиться. IE, представьте, что Клиент 1 раньше был VIP, но каркас инициализации DB изменился, и теперь Клиент 1 больше не VIP, но ваш тест был жестко запрограммирован для загрузки Customer 1 …

Лучший подход – создать экземпляр CustomerDAO и передать его в CustomerFilter, когда он будет создан. (Еще лучший подход – использовать Spring или другую структуру инверсии управления.

Как только вы это сделаете, вы можете быстро издеваться над другими DAO в своем CustomerFilterTest, чтобы вы могли больше контролировать тест,

Без статического DAO тест будет быстрее (без инициализации db) и более надежным (потому что он не сбой при изменении кода инициализации db). Например, в этом случае обеспечение клиента 1 будет и всегда будет VIP, насколько это касается теста.

Выполнение тестов

Статика вызывает реальную проблему при совместном выполнении наборов единичных тестов (например, с сервером непрерывной интеграции). Представьте себе статическую карту сетевых объектов Socket, которые остаются открытыми с одного теста на другой. Первый тест может открыть Socket на порту 8080, но вы забыли очистить карту, когда тест разорвется. Теперь, когда запускается второй тест, он может сбой, когда пытается создать новый Socket для порта 8080, поскольку порт все еще занят. Представьте также, что ссылки Socket в вашей статической коллекции не удаляются, и (за исключением WeakHashMap) никогда не могут быть собраны мусором, что вызывает утечку памяти.

Это обобщенный пример, но в больших системах эта проблема происходит ВСЕ ВРЕМЯ. Люди не думают, что модульные тесты запускают и останавливают свое программное обеспечение повторно в одной и той же JVM, но это хороший тест вашего программного обеспечения, и если у вас есть стремления к высокой доступности, это то, о чем вам нужно знать.

Эти проблемы часто возникают с объектами инфраструктуры, например, вашими базами доступа к БД, кэшированием, сообщениями и протоколированием. Если вы используете Java EE или некоторые из лучших в своем classе фреймворков, они, вероятно, справятся с этим много, но если вы, как я, имеете дело с устаревшей системой, у вас может быть множество пользовательских фреймворков для доступа к этим слоям.

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

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

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

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

Тонкие ошибки

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

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

Когда нить умирает, статический объект не получает сброс или garbage collection. Представьте, что у вас есть stream, называемый «EmailCustomers», и когда он запускается, он заполняет статическую коллекцию String списком адресов электронной почты и затем отправляет по электронной почте каждый из адресов. Допустим, что stream прерывается или отменяется каким-то образом, поэтому ваша платформа высокой доступности перезапускает stream. Затем, когда stream запускается, он перезагружает список клиентов. Но поскольку коллекция является статической, она может сохранить список адресов электронной почты из предыдущей коллекции. Теперь некоторые клиенты могут получать дубликаты писем.

Остаток: статический финал

Использование «статического финала» является фактически эквивалентом Java C #define, хотя существуют технические различия в реализации. AC / C ++ #define перед компиляцией выгружается из кода предварительным процессором. «Статический финал» Java будет содержать резидентную память в стеке. Таким образом, он больше похож на переменную «static const» в C ++, чем на #define.

Резюме

Надеюсь, это поможет объяснить несколько основных причин, почему статика проблематична. Если вы используете современную инфраструктуру Java, такую ​​как Java EE или Spring, и т. Д., Вы не можете столкнуться со многими из этих ситуаций, но если вы работаете с большим количеством устаревшего кода, они могут стать намного более частыми.

Поскольку никто не упомянул об этом: параллелизм. Статические переменные могут удивить вас, если у вас есть несколько streamов чтения и записи статической переменной. Это распространено в веб-приложениях (например, ASP.NET), и это может вызвать некоторые довольно сумасшедшие ошибки. Например, если у вас есть статическая переменная, обновляемая страницей, и страница запрашивается двумя людьми примерно в то же время, один пользователь может получить ожидаемый результат другим пользователем или, что еще хуже.

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

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

* Собственно, об этом сказал Приет Сангха .

если мне пришлось сделать 10 000 вызовов функции внутри classа, я был бы рад сделать этот метод статическим и использовать на нем простой class.methodCall () вместо загромождения памяти с 10 000 экземплярами classа, правильно?

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

Кроме того, статика уменьшает взаимозависимости на других частях кода.

Так делает инкапсуляцию. В больших приложениях статика имеет тенденцию создавать код спагетти и нелегко разрешить рефакторинг или тестирование.

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

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

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

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

Это просто о том, как изолировать логику и дать ей хорошее место. Иногда это оправдывает использование статических методов, примером которых является java.lang.Math . Я думаю, что когда вы XxxUtil большинство своих classов XxxUtil или Xxxhelper , лучше пересмотреть свой дизайн.

Обобщение нескольких основных преимуществ и недостатков использования статических методов в Java:

Преимущества:

  1. Доступен глобально, т. Е. Не связан с каким-либо конкретным экземпляром объекта.
  2. Один экземпляр для JVM.
  3. Доступ к ним возможен с помощью имени classа (объект не требует).
  4. Содержит одно значение, применимое ко всем экземплярам.
  5. Загрузите JVM и запустите его, когда JVM отключится.
  6. Они не изменяют состояние объекта.

Недостатки:

  1. Статические элементы всегда являются частью погоды памяти, которую они используют или нет.
  2. Вы не можете контролировать создание и уничтожение статической переменной. По своей сути они были созданы при загрузке программы и уничтожены при разгрузке программы (или когда JVM отключается).
  3. Вы можете сделать статический stream безопасным, используя синхронизацию, но вам нужны дополнительные усилия.
  4. Если один stream изменит значение статической переменной, которая может сломать функциональность других streamов.
  5. Перед использованием вы должны знать «статические».
  6. Вы не можете переопределять статические методы.
  7. Сериализация не работает с ними.
  8. Они не участвуют в polymorphismе времени выполнения.
  9. Есть проблема с памятью (в некоторой степени, но не настолько, насколько я предполагаю), если используется большое количество статических переменных / методов. Потому что они не будут GC до окончания программы.
  10. Статические методы также трудно проверить.

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

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

Еще одна причина: хрупкость.

Если у вас есть class, большинство людей ожидают, что смогут его создать и использовать по желанию.

Вы можете документировать, что это не так, или защитить его (singleton / factory pattern), но это дополнительная работа и, следовательно, дополнительная стоимость. Даже тогда, в большой компании, есть вероятность, что кто-то попытается в какой-то момент использовать ваш class, не обращая внимания на все приятные комментарии или на завод.

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

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

Преимущества:

Статические элементы / методы используются, как в вспомогательных classах, например, в Math или в classах констант. который помогает другим объектам использовать строки или полезные функции, для которых вам не нужно создавать объект, но вызывается с использованием имени classа. Пример. Объекты singleton вызываются с использованием статической функции.

Недостатки:

Статические элементы являются частью classа и, таким образом, остаются в памяти до тех пор, пока приложение не прекратится и не сможет собраться с мусором. Использование избытка статических элементов когда-либо предсказывает, что вы не можете спроектировать свой продукт и пытаетесь использовать статическое / процедурное программирование. Это означает, что объектно-ориентированный дизайн скомпрометирован. Это может привести к переполнению памяти. Также есть некоторые недостатки, если вы ставите какой-либо метод статическим в Java, например, вы не можете переопределить какой-либо статический метод в Java, поэтому он усложняет тестирование, вы не можете заменить этот метод макетом. Поскольку статический метод поддерживает глобальное состояние, он может создавать тонкую ошибку в параллельной среде, которую трудно обнаружить и исправить.

То, что нужно запомнить:

Статическая переменная будет частью определения classа, а не кучи. Однако статические переменные полезны, когда вы знаете, что будут доступны объекты из нескольких мест. Доступ к статическим ресурсам не является streamобезопасным. Вы можете получить странные / непредсказуемые результаты в поточной среде. Но если ваше единственное чтение статического значения, то использование streamов для него в порядке.

Как инкапсуляция статических прорывов:

Техническая реализация их заключается в том, чтобы обеспечить сохранение состояния во всех экземплярах classа. Проблема в том, что это по сути не ООП, поскольку она не учитывает инкапсуляцию. Если переменная может быть изменена любым экземпляром classа, то основной принцип скрытия инкапсуляции / информации полностью теряется: объект больше не полностью контролирует его состояние. Его состояние теперь зависит от переменных, которые по сути являются глобальными. Мы знаем, что это плохо. Даже частные статические переменные сохраняют состояние на глобальном уровне, но просто ограничивают его доступ. Любой экземпляр объекта может изменять статическую переменную, которая вызывает неоднозначность, поскольку отдельные экземпляры объекта больше не имеют контроля над своим собственным состоянием. State changes can arbitrarily happen without knowledge of an object which relies on that state which is problematic because the object may not work correctly when this happens. Much as it’s often said that “Inheritance breaks encapsulation” statics do this in a far more severe way: By not just exposing internal implementation but also by exposing internal state.

I have just summarized some of the points made in the answers. If you find anything wrong please feel free to correct it.

Scaling: We have exactly one instance of a static variable per JVM. Suppose we are developing a library management system and we decided to put the name of book a static variable as there is only one per book. But if system grows and we are using multiple JVMs then we dont have a way to figure out which book we are dealing with?

Thread-Safety: Both instance variable and static variable need to be controlled when used in multi threaded environment. But in case of an instance variable it does not need protection unless it is explicitly shared between threads but in case of a static variable it is always shared by all the threads in the process.

Testing: Though testable design does not equal to good design but we will rarely observe a good design that is not testable. As static variables represent global state and it gets very difficult to test them.

Reasoning about state: If I create a new instance of a class then we can reason about the state of this instance but if it is having static variables then it could be in any state. Зачем? Because it is possible that the static variable has been modified by some different instance as static variable is shared across instances.

Serialization: Serialization also does not work well with them.

Creation and destruction: Creation and destruction of static variables can not be controlled. Usually they are created and destroyed at program loading and unloading time. It means they are bad for memory management and also add up the initialization time at start up.

But what if we really need them?

But sometimes we may have a genuine need of them. If we really feel the need of many static variables that are shared across the application then one option is to make use of Singleton Design pattern which will have all these variables. Or we can create some object which will have these static variable and can be passed around.

Also if the static variable is marked final it becomes a constant and value assigned to it once cannot be changed. It means it will save us from all the problems we face due to its mutability.

Static variables most importantly creates problem with security of data (any time changed,anyone can change,direct access without object, etc.)

For further info read this Thanks.

I find static variables more convenient to use. And I presume that they are efficient too (Please correct me if I am wrong) because if I had to make 10,000 calls to a function within a class, I would be glad to make the method static and use a straightforward class.methodCall() on it instead of cluttering the memory with 10,000 instances of the class, Right?

I see what you think, but a simple Singleton pattern will do the same without having to instantiate 10 000 objects.

static methods can be used, but only for functions that are related to the object domain and do not need or use internal properties of the object.

например:

 public class WaterContainer { private int size; private int brand; ...etc public static int convertToGallon(int liters)... public static int convertToLiters(int gallon)... } 

The issue of ‘Statics being evil’ is more of an issue about global state. The appropriate time for a variable to be static, is if it does not ever have more than one state; IE tools that should be accessible by the entire framework and always return the same results for the same method calls are never ‘evil’ as statics. As to your comment:

I find static variables more convenient to use. And I presume that they are efficient too

Statics are the ideal and efficient choice for variables/classes that do not ever change .

The problem with global state is the inherent inconsistency that it can create. Documentation about unit tests often address this issue, since any time there is a global state that can be accessed by more than multiple unrelated objects, your unit tests will be incomplete, and not ‘unit’ grained. As mentioned in this article about global state and singletons , if object A and B are unrelated (as in one is not expressly given reference to another), then A should not be able to affect the state of B.

There are some exceptions to the ban global state in good code, such as the clock. Time is global, and–in some sense–it changes the state of objects without having a coded relationship.

Seems to me that you’re asking about static variables but you also point out static methods in your examples.

Static variables are not evil – they have its adoption as global variables like constants in most cases combined with final modifier, but as it said don’t overuse them.

Static methods aka utility method. It isn’t generally a bad practice to use them but major concern is that they might obstruct testing.

As a example of great java project that use a lot of statics and do it right way please look at Play! framework . There is also discussion about it in SO.

Static variables/methods combined with static import are also widely used in libraries that facilitate declarative programming in java like: make it easy or Hamcrest . It wouldn’t be possible without a lot of static variables and methods.

So static variables (and methods) are good but use them wisely!

My $.02 is that several of these answers are confusing the issue, rather than saying “statics are bad” I think its better to talk about scoping and instances.

What I would say is that a static is a “class” variables – it represenst a value that is shared across all instances of that class. Typically it should be scoped that way as well (protected or private to class and its instances).

If you plan to put class-level behavior around it and expose it to other code, then a singleton may be a better solution to support changes in the future (as @Jessica suggested). This is because you can use interfaces at the instance/singleton level in ways that you can not use at the class level – in particular inheritance.

Some thoughts on why I think some of the aspects in other answers are not core to the question…

Statics are not “global”. In Java scoping is controlled separately from static/instance.

Concurrency is no less dangerous for statics than instance methods. It’s still state that needs to be protected. Sure you may have 1000 instances with an instance variable each and only one static variable, but if the code accessing either isn’t written in a thread-safe way you are still screwed – it just may take a little longer for you to realize it.

Managing life cycle is an interesting argument, but I think it’s a less important one. I don’t see why its any harder to manage a pair of class methods like init()/clear() than the creation and destroying of a singleton instance. In fact, some might say a singleton is a little more complicated due to GC.

PS, In terms of Smalltalk, many of its dialects do have class variables, but in Smalltalk classes are actually instances of Metaclass so they are really are variables on the Metaclass instance. Still, I would apply the same rule of thumb. If they are being used for shared state across instances then ok. If they are supporting public functionality you should look at a Singleton. Sigh, I sure do miss Smalltalk….

There’s nothing wrong with static variables per se. It’s just the Java syntax that’s broken. Each Java class actually defines two structures- a singleton object which encapsulates static variables, and an instance. Defining both in the same source block is pure evil, and results in a code that’s hard to read. Scala did that right.

a) Reason about programs.

If you have a small- to midsize-program, where the static variable Global.foo is accessed, the call to it normally comes from nowhere – there is no path, and therefore no timeline, how the variable comes to the place, where it is used. Now how do I know who set it to its actual value? How do I know, what happens, if I modify it right now? I have grep over the whole source, to collect all accesses, to know, what is going on.

If you know how you use it, because you just wrote the code, the problem is invisible, but if you try to understand foreign code, you will understand.

b) Do you really only need one?

Static variables often prevent multiple programs of the same kind running in the same JVM with different values. You often don’t foresee usages, where more than one instance of your program is useful, but if it evolves, or if it is useful for others, they might experience situations, where they would like to start more than one instance of your program.

Only more or less useless code which will not be used by many people over a longer time in an intensive way might go well with static variables.

There are two main questions in your post.

First, about static variables. Static variables are completelly unnecesary and it’s use can be avoided easily. In OOP languajes in general, and in Java particularlly, function parameters are pased by reference, this is to say, if you pass an object to a funciont, you are passing a pointer to the object, so you dont need to define static variables since you can pass a pointer to the object to any scope that needs this information. Even if this implies that yo will fill your memory with pointers, this will not necesary represent a poor performance because actual memory pagging systems are optimized to handle with this, and they will maintain in memory the pages referenced by the pointers you passed to the new scope; usage of static variables may cause the system to load the memory page where they are stored when they need to be accessed (this will happen if the page has not been accesed in a long time). A good practice is to put all that static stuf together in some little “configuration clases”, this will ensure the system puts it all in the same memory page.

Second, about static methods. Static methods are not so bad, but they can quickly reduce performance. For example, think about a method that compares two objects of a class and returns a value indicating which of the objects is bigger (tipical comparison method) this method can be static or not, but when invoking it the non static form will be more eficient since it will have to solve only two references (one for each object) face to the three references that will have to solve the static version of the same method (one for the class plus two, one for each object). But as I say, this is not so bad, if we take a look at the Math class, we can find a lot of math functions defined as static methods. This is really more eficient than putting all these methods in the class defining the numbers, because most of them are rarelly used and including all of them in the number class will cause the class to be very complex and consume a lot of resources unnecesarilly.

In concluson: Avoid the use of static variables and find the correct performance equilibrium when dealing with static or non static methods.

PS: Sorry for my english.

everything (can:) have its purpose, if you have bunch of threads that needs to share/cache data and also all accessible memory (so you dont split into contexts within one JVM) the static is best choice

-> of course you can force just one instance, but why?
i find some of the comments in this thread evil, not the statics 😉

All the answers above show why statics are bad. The reason they are evil is because it gives the false impression that you are writing object oriented code, when in fact you are not. That is just plain evil.

Static variables are not good nor evil. They represent attributes that describe the whole class and not a particular instance. If you need to have a counter for all the instances of a certain class, a static variable would be the right place to hold the value.

Problems appear when you try to use static variables for holding instance related values.

There are plenty of good answers here, adding to it,

Memory: Static variables are live as long as the class loader lives[in general till VM dies], but this is only in-case of bulk objects/references stored as static.

Modularization: consider concepts like IOC, dependencyInjection, proxy etc.. All are completely against tightly coupling/static implementations.

Other Con’s: Thread Safety, Testability

Think that if you have an application with many users and you have define a static form, then every user will modify all other forms of other users too.

Static means global, whenever you mark a variable as static , you make it visible and shared between all instances of a class.

In multi-threaded environments, marking a variable as static would allow multiple threads to access and modify it concurrently and that’s would leave it in inconsistent state and lead to several serious problems, the debugging of such problems is very harmful.

Although developers normally tend to protect their static variables from concurrent modifications using for example Synchronized blocks, it is a time-consuming task to always surround each modification with a Synchronized block and there’s a high possibility that the developer forget to protect some modification code by mistake.

The common usage of static variables is for defining constants, try to diminish the usage of them as much as you can unless you have a very specific business case which couldn’t be solved better without static variable ie when you define an auto generated ID field in a class.

For much details, check Static keyword in java

I think excessive uses of global variables with static keyword will also leads to memory leakage at some point of instance in the applica

  • Почему я не могу инициализировать нестационарный статический член или статический массив в classе?
  • Возможны ли переменные статического classа?
  • Файлы Jango Static 404
  • Поведение конечного статического метода
  • Создание статической сборки Mac OS XC
  • Неопределенная ссылка на статическую переменную c ++
  • Зачем выбирать статический class по сравнению с одноэлементной реализацией?
  • Определение статических элементов в C ++
  • В чем причина «нестатического метода нельзя ссылаться из статического контекста»?
  • Статические методы унаследованы в Java?
  • Что означает `public static void main args`?
  • Interesting Posts

    Звук не работает в iPhone Simulator?

    Как узнать, сколько строк кода есть в проекте Xcode?

    Как мне зарегистрироваться на C # без использования сторонних библиотек?

    Как проверить, содержит ли строка подстроку в Bash

    Исключение SQLite: SQLite Занято

    Как изменить значки меню навигации и переполнения панели инструментов (appcompat v7)?

    Скорость выделения шатра

    Не удается удалить файл: система не может найти указанный файл

    Сделать новый вид активности за старым во время перехода

    Windows Phone 7 и собственный C ++ / CLI

    Как разместить приложение Node.Js в режиме совместного доступа

    Извлечение размеров streamа H264Video

    Понимание регулярного выражения в Java: split (“\ t”) vs split (“\\ t”) – когда они оба работают, и когда они должны использоваться

    Сделайте снимок экрана прокручивающегося окна, которое включает в себя части экрана

    Как удалить пустую папку с помощью thumbs.db без отключения миниатюр

    Давайте будем гением компьютера.