Почему статические переменные считаются злыми? - PullRequest
585 голосов
/ 11 августа 2011

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

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

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

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

Ответы [ 29 ]

9 голосов
/ 11 августа 2011

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

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

6 голосов
/ 20 августа 2011

Мне кажется, что вы спрашиваете о статических переменных, но вы также указываете статические методы в своих примерах.

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

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

Как пример отличного Java-проекта, который использует много статики и делает это правильно.Кстати, пожалуйста, посмотрите на Играть!основа .Существует также обсуждение об этом в SO.

Статические переменные / методы в сочетании со статическим импортом также широко используются в библиотеках, которые облегчают декларативное программирование в Java, например: облегчают или Hamcrest .Это было бы невозможно без большого количества статических переменных и методов.

Так что статические переменные (и методы) хороши, но используйте их с умом!

6 голосов
/ 20 мая 2016

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

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

Thread-Safety: И переменная экземпляра, и статическая переменная должныконтролироваться при использовании в многопоточной среде.Но в случае переменной экземпляра она не нуждается в защите, если она явно не разделена между потоками, но в случае статической переменной она всегда используется всеми потоками в процессе.

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

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

Сериализация: Сериализация также плохо работает с ними.

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

Но что, если они нам действительно нужны?

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

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

6 голосов
/ 11 августа 2011

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

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

6 голосов
/ 11 августа 2011

Статические переменные наиболее важны для обеспечения безопасности данных (при любом изменении, любой может измениться, прямой доступ без объекта и т. Д.)1005 *

5 голосов
/ 12 августа 2011

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

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

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

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

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

4 голосов
/ 11 августа 2011

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

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

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

например:

public class WaterContainer {
    private int size;
    private int brand;
    ...etc

    public static int convertToGallon(int liters)...

    public static int convertToLiters(int gallon)...

}
4 голосов
/ 12 февраля 2014

Нет ничего плохого в статических переменных как таковых.Это просто синтаксис Java, который нарушен.Каждый класс Java фактически определяет две структуры - одноэлементный объект, который инкапсулирует статические переменные, и экземпляр.Определение обоих в одном и том же исходном блоке - чистое зло, и в результате получается код, который трудно прочитать.Скала сделала это правильно.

4 голосов
/ 12 августа 2011

Вопрос о том, что статика является злом, - это скорее проблема глобального состояния. Подходящее время для того, чтобы переменная была статической, - это если у нее никогда не было более одного состояния; Инструменты IE, которые должны быть доступны для всей среды и всегда возвращать одинаковые результаты для одних и тех же вызовов методов, никогда не являются «злыми», как статические. Что касается вашего комментария:

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

Статика - идеальный и эффективный выбор для переменных / классов, которые никогда не меняются .

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

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

4 голосов
/ 17 августа 2011

Мои $ .02 состоят в том, что некоторые из этих ответов сбивают с толку проблему, вместо того, чтобы сказать «статика плохая». Я думаю, что лучше поговорить о масштабах и случаях.

Я бы сказал, чтоstatic - это переменные «класса» - они представляют значение, которое является общим для всех экземпляров этого класса.Как правило, он должен быть ограничен таким же образом (защищенным или закрытым для класса и его экземпляров).

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

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

Статика не "глобальная".В Java область видимости контролируется отдельно от static / instance.

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

Управление жизненным циклом - интересный аргумент, но я думаю, что он менее важен.Я не понимаю, почему так сложно управлять парой методов класса, таких как init () / clear (), чем создание и уничтожение экземпляра синглтона.Фактически, некоторые могут сказать, что синглтон немного сложнее из-за GC.

PS. С точки зрения Smalltalk, многие из его диалектов имеют переменные класса, но в классах Smalltalk фактически являются экземплярами Metaclass, поэтому онидействительно являются переменными в экземпляре Metaclass.Тем не менее, я бы применил то же правило.Если они используются для общего состояния между экземплярами, тогда хорошо.Если они поддерживают публичную функциональность, вам стоит взглянуть на Singleton.Вздох, я действительно скучаю по Smalltalk ....

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