В Java статические методы, плюсы и минусы
Я не использовал много статических методов раньше, но совсем недавно я склонен использовать больше из них. Например, если я хочу установить логический флаг в классе или acess один без необходимости передавать фактический объект через классы.
например:
public class MainLoop
{
private static volatile boolean finished = false;
public void run()
{
while ( !finished )
{
// Do stuff
}
}
// Can be used to shut the application down from other classes, without having the actual object
public static void endApplication()
{
MainLoop.finished = true;
}
}
это то, чего я должен избегать? Лучше ли передать объект, чтобы вы могли использовать методы objects? Делает логическое finished
считается глобальным сейчас, или это так же безопасно?
4 ответов
проблема с использованием статической переменной в этом случае заключается в том, что если вы создадите два (или более) экземпляра MainLoop, написание кода, который выглядит так, как будто он завершает работу только одного из экземпляров, фактически завершит работу обоих из них:
MainLoop mainLoop1 = new MainLoop();
MainLoop mainLoop2 = new MainLoop();
new Thread(mainLoop1).start();
new Thread(mainLoop2).start();
mainLoop1.finished = true; // static variable also shuts down mainLoop2
Это только одна из причин (среди многих) для выбора не использовать статические переменные. Даже если ваша программа сегодня создает только один MainLoop, возможно, что в будущем у вас будут причины создать многие из них: для модульного тестирования или чтобы реализовать классную новую функцию.
вы можете думать, "если что-нибудь случится, я просто рефакторинг программы, чтобы использовать переменные-члены, а не статические переменные."Но, как правило, более эффективно оплачивать расходы вперед и с самого начала внедрять модульное проектирование в программу.
нет никаких сомнений в том, что статика часто упрощает написание быстрой и грязной программы. Но для важного / сложного кода, который вы собираетесь тестировать, поддерживать, выращивать, делиться и использовать в течение многих лет приходите, статические переменные обычно рекомендуются против.
как отмечали другие ответы на этот вопрос, статическая переменная является своего рода глобальной переменной. И есть много информации о том, почему (как правило) глобальные переменные are плохо.
да, передача объектов вокруг лучше. Использование одноэлементных или статических методов делает программирование OO похожим на процедурное программирование. Синглтон несколько лучше, потому что вы можете по крайней мере заставить его реализовать интерфейсы или расширить абстрактный класс, но обычно это запах дизайна.
и смешивание методов экземпляра со статическими переменными, как вы делаете, еще более запутанно: у вас может быть несколько объектов, но вы останавливаете их все сразу, потому что они все останавливаются, когда статические изменения переменных.
Это то, чего я должен избегать?
В общем, да. Статика представляет глобальные государство. Глобальное состояние трудно рассуждать, трудно тестировать изолированно и, как правило, имеет более высокие требования к безопасности потоков.
Если я хочу проверить, что происходит с объект в определенном состоянии я могу просто создать объект, поместить его в это состояние, выполнить мои тесты и позволить ему собрать мусор.
Если я хочу проверьте, что происходит с глобальные состояние, мне нужно убедиться, что я сбросил все это в конце моего теста (или, возможно, в начале каждого теста). Тесты теперь будут мешать друг другу, если я не подумаю об этом.
конечно, если статический метод не должен влиять на какое - либо состояние-т. е. если это чисто - тогда все становится несколько лучше. В этот момент все, что вы теряете, это способность заменить реализация этого метода, например, когда проверяю что-то, что это называет.
в общем, внеся finished
статический, как вы создаете ситуацию, когда может быть только один экземпляр вашего MainLoop
класс-исполнителем run
в любой момент времени. Если существует более одного экземпляра, то установка finished
закончит их всех -- не то, что обычно нужные.
однако, в этом особенности сценарий, где вы хотите "завершить приложение", предположительно означает, что вы хотите, чтобы все экземпляры MainLoop
подход может быть оправданный.
однако количество ситуаций, в которых этот подход может быть оправдан, мало, и "более чистым" способом обработки этого сценария было бы сохранить static
список экземпляров и работать через список, установив переменную экземпляра finished
в каждом случае. Это позволяет также завершить отдельные экземпляры,дает вам естественное количество существующих экземпляров и т. д.