статических - чем плохи статические методы java
Если частные вспомогательные методы являются статическими, если они могут быть статическими (14)
или какой-либо конкретной причине не [объявлять их как статические]?
Сохраняя их как методы экземпляра, вы позволяете себе позже выполнять другую реализацию.
Это может показаться глупым (и на самом деле это было бы, если бы эти методы использовались только вами в 50-строчной программе), но в более крупных приложениях или в библиотеках, используемых кем-то другим, вы можете выбрать лучшую реализацию, но не хотите сломать существующий код.
Таким образом, вы создаете подкласс и возвращаете его в новых версиях, и поскольку методы были объявлены как методы экземпляра, вы просто позволяете полиморфизму выполнять свою работу.
Кроме того, вы можете извлечь выгоду из того, чтобы сделать конструктор закрытым и предоставить статический заводский метод по той же причине.
Поэтому моя рекомендация состоит в том, чтобы сохранить их как методы экземпляра и избежать статики, если это возможно. Используйте динамизм, предоставляемый языком.
Хотя он не имеет прямого отношения к обсуждению метода статического vs экземпляра, он затрагивает некоторые интересные моменты в дизайне API.
Предположим, у меня есть класс, созданный для создания экземпляра. У меня есть несколько частных «вспомогательных» методов внутри класса, которые не требуют доступа к любому из членов класса и действуют исключительно на их аргументы, возвращая результат.
Есть ли какая-то конкретная причина для указания computeOne и computeMore как статических методов - или каких-либо особых причин?
Конечно, проще всего оставить их нестационарными, хотя они могут быть статическими, не вызывая никаких проблем.
Без статического модификатора вы не можете понять, что метод является безстоящим без дополнительного анализа, который можно легко сделать, когда вы (повторно) напишите метод.
Затем «статический» модификатор может дать вам идеи о рефакторинге, помимо других вещей, которые другие могут найти неиспользованными. Например, перемещение метода в некоторый класс Utility или преобразование его в метод участника.
Более конкретно, к примеру, который вы указали, кажется, что цель определения этих методов больше для ясности кода, когда вы его читаете, чем для функциональности (они определены как частные). В этом случае переход со статикой действительно ничего не делает для вас, так как целью статического является раскрытие функциональности класса.
Если метод в основном является просто подпрограммой, которая никогда не будет предусматривать использование информации о состоянии, объявите ее статичной.
Это позволяет использовать его в других статических методах или в инициализации класса, то есть:
Как и многие люди, сделайте это как статичное ! Вот правило большого пальца, которое я следую: если вы считаете, что метод - это просто математическая функция, то есть он не имеет состояния, не включает никаких переменных экземпляра (=> нет синих цветовых варов [в затмении] в методе), а результат метод будет одинаковым для числа «n» вызовов (с теми же параметрами, конечно), затем отметьте этот метод как STATIC.
И если вы считаете, что этот метод будет полезен для другого класса, тогда переместите его в класс Util, в противном случае добавьте метод как частный в sameclass. (минимизация доступности)
Мое предпочтение в таких случаях - сделать computeOne и computeMore статические методы. Причина: инкапсуляция. Чем меньше кода, доступ к реализации вашего класса, тем лучше.
В примере, который вы даете, вы указываете, что computeOne и computeMore не должны иметь доступ к внутренним функциям класса, так почему бы предоставить разработчикам этого класса возможность вмешиваться в работу с внутренними компонентами.
Одна из причин заключается в том, что при прочих равных условиях вызовы статических методов должны быть быстрее. Статические методы не могут быть виртуальными и не должны подразумевать эту ссылку.
Одна из причин, по которой вы можете захотеть объявить статические вспомогательные методы, - это если вам нужно вызвать их в конструкторе класса «до» this или super . Например:
Это немного надуманный пример, но ясно, что recoverInt не может быть методом экземпляра в этом случае.
Ответ . это зависит.
Если элемент - это переменная экземпляра, специфичная для объекта, с которым вы имеете дело, то зачем передавать его как параметр вообще?
любой метод, который не принимает никакой информации из поля и не помещает какую-либо информацию в поле, не должен быть методом экземпляра. Любой метод, который не использует или не изменяет какие-либо поля в его классе или объекте, также может быть статическим методом.
Это может привести к немного меньшему байт-коду, поскольку статические методы не получат доступ к this . Я не думаю, что это имеет какое-то значение в скорости (и если бы это было так, это, вероятно, было бы слишком маленьким, чтобы иметь значение в целом).
Я бы сделал их статичными, так как я вообще делаю это, если это вообще возможно. Но это только я.
EDIT: этот ответ продолжает задерживаться, возможно, из-за необоснованного утверждения о размере байт-кода. Поэтому я действительно проведу тест.
Байт-код (извлекается с помощью javap -c -private TestBytecodeSize ):
Вызов статического метода принимает два байткода (byteops?): iconst_0 (для аргумента) и invokestatic . Вызов нестатического метода занимает три: aload_1 (для объекта TestBytecodeSize , я полагаю), iconst_0 (для аргумента) и invokespecial . (Обратите внимание, что если они не были частными методами, это было бы invokevirtual вместо invokespecial , см. JLS §7.7. Вызов методов .)
Теперь, как я уже сказал, я не ожидаю, что между этими двумя invokestatic будет большая разница в производительности, кроме того, что invokestatic требует меньше байт-кода. invokestatic и invokespecial должны быть немного быстрее, чем invokevirtual , поскольку оба они используют статическое связывание вместо динамического, но я понятия не имею, является ли он быстрее, чем другой. Я тоже не могу найти хороших ссылок. Самое близкое, что я могу найти, это статья 1997 JavaWorld , в которой в основном говорится, что я только что сказал:
Самые быстрые команды, скорее всего, будут invokespecial и invokestatic , потому что методы, вызванные этими инструкциями, статически связаны. Когда JVM разрешает символическую ссылку для этих инструкций и заменяет ее прямой ссылкой, эта прямая ссылка, вероятно, будет содержать указатель на фактические байт-коды.
Но с 1997 года многое изменилось.
Итак, в заключение . Думаю, я все еще придерживаюсь того, что я сказал раньше. Скорость не должна быть причиной выбора одного над другим, поскольку в лучшем случае это будет микро-оптимизация.
Я не могу думать о явных преимуществах для частного статического метода. Тем не менее, нет никаких особых преимуществ, чтобы сделать их нестационарными. Это главным образом вопрос презентации: вы можете сделать их статичными, чтобы четко подчеркнуть тот факт, что они не изменяют объект.
Для метода с разными правами доступа я думаю, что есть два основных аргумента:
- статические методы можно вызывать без создания экземпляра объекта, который может быть полезен
- статические методы не могут быть унаследованы, что может быть проблемой, если вам нужен полиморфизм (но он не имеет отношения к частным методам).
Кроме того, разница довольно небольшая, и я сильно сомневаюсь, что дополнительный этот указатель, переданный методу экземпляра, имеет существенное значение.
Я предпочитаю, чтобы такие вспомогательные методы были private static ; что позволит читателю понять, что они не будут изменять состояние объекта. В моей среде IDE также будут отображаться вызовы статических методов курсивом, поэтому я буду знать, что метод статичен, не глядя на подпись.
Я хотел бы уточнить некоторые вещи, которые другие плакаты сказали, поскольку они дают неверную информацию.
Во-первых, поскольку методы являются частными, даже если вы объявляете их static, вы не сможете получить к ним доступ за пределами этого класса. Во-вторых, они являются частными, поэтому вы не можете переопределить их в подклассе, поэтому статические или нестатические значения не имеют никакого значения. В-третьих, нестатический частный метод также можно вызывать из конструктора класса, он не обязательно должен быть статическим.
Теперь придет к вашему вопросу, если частный метод помощника должен быть определен как статический или нестатический. Я поеду с ответом Стива в качестве частного статического метода, который показывает, что этот метод не имеет состояния, поскольку я также следую этому правилу при кодировании.