Статические переменные: хорошие или плохие?
Возможный дубликат:
Почему статические переменные считаются злыми?
У меня есть привычка широко использовать статические переменные во всех моих программах, особенно когда я работаю с Android. Я склонен использовать их, потому что иногда кажется, что громоздко отправить 10 или более значений с помощью намерений. Таким образом, я просто объявляю их как статические переменные и легко обращаюсь к ним в других классах, используя оператор "точка". Еще одна причина использования статических переменных - это когда я использую класс Утилиты, который будет использоваться во всем приложении. Как и код, приведенный ниже, я могу использовать переменные в разных действиях.
Utility.java
public class Utility {
public static Facebook fb;
public static AsyncFacebookRunner fbAsyncRunner;
public static String[] fbPermissions = {"email", "read_stream", "user_birthday"};
public static final String PREF_UTILITY_FILE_NAME = "PrefUtilityFile";
public static SharedPreferences prefs;
public static Editor editor;
public static String access_token;
public static long expires;
}
Я искал в Интернете похожие вопросы и навел этот и этот, но они, похоже, не дать окончательный ответ на этот вопрос. И в большинстве мест я вижу противоречивые мнения и, следовательно, совершенно смущен.
Является ли это хорошей практикой программирования или плохой? Должен ли я использовать ее или нет?
Ответы
Ответ 1
Вы можете заменить все ваши статические поля объектом "Контекст", который вы можете передать или создать Singleton. Можно удалить почти все ваши статические поля. Является ли это хорошей идеей или нет, зависит от вас, но я бы не стал предполагать, что использовать экземпляры полей намного сложнее.
Кстати: я бы предложил
- размещение статических полей/констант с классом или пакетом, который их использует
- относить статические массивы как неизменные, если возможно, сделать их
final
.
Вы можете использовать нестатический Контекст с
public class Context {
public static final String PREF_UTILITY_FILE_NAME = "PrefUtilityFile";
public Facebook fb;
public AsyncFacebookRunner fbAsyncRunner;
public String[] fbPermissions = {"email", "read_stream", "user_birthday"};
public SharedPreferences prefs;
public Editor editor;
public String access_token;
public long expires;
}
// pass to constructor as required
class UsesContext {
final Context context;
public UsesContext(Context context) {
this.context = context;
}
public void method() {
// can use context
}
}
Это позволяет создавать модульные тесты с несколькими контекстами.
Единственное, что я оставил статичным, это константы.
Ответ 2
Эта практика программирования плоха в чисто объектно-ориентированных языках (например, Java), потому что она подрывает парадигму объектно-ориентированного программирования. Они работают, но как только вы осознаете, что вам нужно больше одной версии, для этого вам понадобится много рефакторинга.
Если вы считаете, что передача слишком большого количества параметров с помощью вызовов методов является громоздкой. Просто создайте объект, содержащий все из них (см. Ответ Питера Лори, объект "Контекст" ) и передайте только этот объект. Затем вы можете снова использовать свою "простую точечную нотацию" на этом объекте.
Следующий пункт: Тестирование. Если вам нужно заменить некоторые статические поля прокси или другими предметами тестирования для модульных тестов, вы в основном завинчены. С помощью объекта контекста вы можете просто передать другой объект контекста в модульные тесты.
Класс Utility
, который вы упомянули, в основном является хорошим кандидатом для такого объекта контекста. Просто сделайте все свои поля нестатичными и передайте объект этого класса в код, который ему нужен.
Я могу рассказать вам о одном примере, где я был привинчен с помощью статики: однажды написал компилятор. И так как я думал, что во время прогона компиляции существует много контекстных вещей, которые необходимы только один раз (например, таблица символов), я добавил их все как статические переменные. Позже я решил разрешить многопоточную компиляцию и "серверный" режим, когда компилятор работает все время в режиме ожидания до тех пор, пока клиент не отправит запрос компиляции (это сохраняет длительное время запуска Java). Теперь я был ввернут. Теперь было более одного параллельного контекста (параллельные потоки компилятора), но весь контекст был разделен статическими переменными. Мне понадобилась около одной недели, чтобы заменить все статики на объекты контекста и ввели многочисленные ошибки.
Ответ 3
Я все для статических переменных, если вы продолжаете регулярно их использовать, и значения никогда не меняются, если вы делаете их окончательными.
Почему все труднее?
Это то, что все статические переменные.
В основном, они предоставляют общую точку доступа, к которой вы можете получить доступ из любого контекста (статический, программный, внешний).
Вы в основном заявляете, что входная дверь здесь, и она желтая. Кто-то, выглядывающий извне, увидит желтую дверь. Кто-то на внутренней ходьбе увидит дверь и станет желтой.
Кто-то в комнате может смотреть в коридор и видеть, что он желтый.
И если вы нарисуете его красным, он будет хорошо виден всем.
Кроме того, всегда будет один экземпляр во всей программе ENTIRE с тем же значением. который сохраняет память.
возьмите, например,
class test {
public int ten = 10;
public test() {
}
}
Каждый раз, когда вы создаете new test()
, для десяти переменных будет назначено целое число памяти. Поэтому, если у вас есть 10 тестовых экземпляров, у вас будет 10 отдельных целых чисел, имеющих одинаковое значение.
если у вас есть этот
class test {
public static int ten = 10;
public test() {
}
}
и у вас есть десять тестовых экземпляров, у вас будет только один целочисленный экземпляр десять. Это экономит память, сбор мусора. Хотя я только советую это для постоянных списков/переменных, которые не меняются, и вы можете позволить себе хранить в памяти неопределенно. Не делайте этого с каждой переменной. Сделайте это для больших вещей, как образ, который вы повторно используете снова и снова. Не рекомендуется хранить одно и то же изображение в памяти несколько раз.
Когда я изначально написал свой ответ, я не знал, как работают статические переменные. Я перепутал static final
и static
. По статическим переменным вы можете назначить новые значения. статические окончательные неизменяемы. они не могут быть изменены.
Ответ 4
Переменные, которые объявляются статическими, остаются в памяти до тех пор, пока программа не выполнится, тем самым получив дополнительное пространство.
Использование статики может быть полезно, если вы хотите использовать/сохранять значение в течение длительного периода времени, однако объявление всех переменных как статических не рекомендуется и не является хорошей практикой. Если у вас есть привычка объявлять все значение как статическое, ваша программа будет потреблять ненужную память.
Кроме этой статической переменной не соответствует концепции OOPS, где определяются области, абстракция и инкапсуляция вместе с объектом вскипания. Через которые вы можете вызывать и удалять переменные по своему усмотрению.
Самый большой недостаток использования статических переменных появится, если вы работаете в ограниченном пространстве памяти (например, в мобильных приложениях), в этом случае приложение будет аварийно завершено, если оно будет перегружено переменными и уменьшит объем памяти.
Если вы хотите сохранить значение на постоянной основе, существуют другие способы, такие как база данных, файлы и т.д. упрощают работу и становятся более чистыми.
Только мои 2 цента.
Ответ 5
Bad. См. Отключение статики.
По-моему, статические переменные содержат один или несколько объектов, но эти объекты плохо сформированы: не организованы в классы (нет иерархии типов), плохая инкапсуляция, ограниченная одним экземпляром (это может вызвать проблемы, когда в будущем несколько требуемые экземпляры).