Когда использовать статические методы
Мне интересно, когда использовать статические методы? Скажем, если у меня есть класс с несколькими приемниками и установщиками, методом или двумя, и я хочу, чтобы эти методы вызывались только для объекта экземпляра класса. Означает ли это, что я должен использовать статический метод?
Пример:
Obj x = new Obj();
x.someMethod();
...или:
Obj.someMethod(); // Is this the static way?
Я в замешательстве!
Переведено автоматически
Ответ 1
Одно практическое правило: спросите себя: "Имеет ли смысл вызывать этот метод, даже если объект еще не создан?" Если да, то он определенно должен быть статическим.
Итак, в классе Car
у вас может быть метод:
double convertMpgToKpl(double mpg)
...который был бы статическим, потому что можно было бы узнать, во что преобразуется 35mpg, даже если никто никогда не создавал Car
. Но этот метод (который устанавливает эффективность одного конкретного Car
):
void setMileage(double mpg)
...не может быть статическим, поскольку немыслимо вызвать метод до того, как какой-либо Car
был создан.
(Кстати, обратное не всегда верно: иногда у вас может быть метод, который включает два Car
объекта, и вы все равно хотите, чтобы он был статическим. Например.:
Car theMoreEfficientOf(Car c1, Car c2)
Хотя это можно было бы преобразовать в нестатическую версию, некоторые утверждают, что, поскольку нет "привилегированного" выбора того, что Car
важнее, вы не должны заставлять вызывающую программу выбирать один из них Car
в качестве объекта, для которого вы будете вызывать метод. Однако на эту ситуацию приходится довольно небольшая доля всех статических методов.
Ответ 2
Определяйте статические методы только в следующих сценариях:
- Если вы пишете служебные классы и их не предполагается изменять.
- Если метод не использует какую-либо переменную экземпляра.
- Если какая-либо операция не зависит от создания экземпляра.
- Если есть какой-то код, который может быть легко общим для всех методов экземпляра, извлеките этот код в статический метод.
- Если вы уверены, что определение метода никогда не будет изменено или переопределено. Поскольку статические методы не могут быть переопределены.
Ответ 3
Есть несколько веских причин для использования статических методов:
Производительность: если вы хотите запустить какой-то код и не хотите создавать для этого экземпляр дополнительного объекта, поместите его в статический метод. JVM также может значительно оптимизировать статические методы (кажется, я когда-то читал заявление Джеймса Гослинга о том, что вам не нужны пользовательские инструкции в JVM, поскольку статические методы будут такими же быстрыми, но не смог найти источник - таким образом, это может быть полностью ложным). Да, это микрооптимизация, и, вероятно, ненужная. И мы, программисты, никогда не делаем ненужных вещей только потому, что они классные, верно?
Практичность: вместо вызова
new Util().method(arg)
вызывайтеUtil.method(arg)
илиmethod(arg)
со статическим импортом. Проще, короче.Добавление методов: вы действительно хотели, чтобы в строке класса был
removeSpecialChars()
метод экземпляра, но его там нет (и не должно быть, поскольку специальные символы вашего проекта могут отличаться от символов другого проекта), и вы не можете его добавить (поскольку Java несколько вменяем), поэтому вы создаете служебный класс и вызываетеremoveSpecialChars(s)
вместоs.removeSpecialChars()
. Сладко.Чистота: принимая некоторые меры предосторожности, ваш статический метод будет чистой функцией, то есть единственное, от чего он зависит, - это его параметры. Данные поступают, данные выводятся. Это проще читать и отлаживать, поскольку вам не нужно беспокоиться о причудах наследования. Вы также можете сделать это с помощью методов экземпляра, но компилятор немного больше поможет вам со статическими методами (не разрешая ссылки на атрибуты экземпляра, переопределяя методы и т.д.).
Вам также придется создать статический метод, если вы хотите создать синглтон, но ... не делайте этого. Я имею в виду, подумайте дважды.
Теперь, что более важно, почему вы не хотели бы создавать статический метод? По сути, полиморфизм выходит за рамки. Вы не сможете переопределить этот метод, ни объявлять это в интерфейсе (до Java 8). Это требует от вашего дизайна большой гибкости. Кроме того, если вам нужно состояние, вы в конечном итоге столкнетесь с множеством ошибок параллелизма и / или узких мест, если не будете осторожны.
Ответ 4
После прочтения статей Миско я считаю, что статические методы плохи с точки зрения тестирования. Вместо этого у вас должны быть фабрики (возможно, с помощью инструмента внедрения зависимостей, такого как Guice).
как мне убедиться, что у меня есть только один из них
есть только одно из чего-то Проблема “как мне убедиться, что у меня есть только одно из чего-то”, удачно обойдена стороной. Вы создаете экземпляр только одного ApplicationFactory в вашем main, и в результате вы создаете только один экземпляр всех ваших singletons.
Основная проблема со статическими методами заключается в том, что они являются процедурным кодом
Основная проблема со статическими методами заключается в том, что они представляют собой процедурный код. Я понятия не имею, как модульно тестировать процедурный код. Модульное тестирование предполагает, что я могу создать экземпляр части моего приложения изолированно. Во время создания экземпляра я подключаю зависимости с помощью mocks / friendlies, которые заменяют реальные зависимости. При процедурном программировании "подключать" нечего, поскольку объектов нет, код и данные разделены.