Допустим, у меня есть класс, предназначенный для реализации. У меня есть несколько частных «вспомогательных» методов внутри класса, которые не требуют доступа ни к одному из членов класса и работают исключительно с их аргументами, возвращая результат.
public class Example {
private Something member;
public double compute() {
double total = 0;
total += computeOne(member);
total += computeMore(member);
return total;
}
private double computeOne(Something arg) { ... }
private double computeMore(Something arg) {... }
}
Есть ли какая-то конкретная причина для указания computeOne
и computeMore
как статические методы - или какая-то особая причина для этого?
Конечно, проще всего оставить их нестатичными, хотя они могут быть статичными, не вызывая проблем.
java
static
methods
static-methods
avalys
источник
источник
Ответы:
Я предпочитаю, чтобы такие вспомогательные методы были
private static
; что даст понять читателю, что они не будут изменять состояние объекта. Моя IDE также будет показывать вызовы статических методов курсивом, поэтому я буду знать, что метод является статическим, не просматривая сигнатуру.источник
protected static
что делает их очень легко тестируемыми в тестовом классе в том же пакете.static
(если мы просто хотим его для тестирования).Это может привести к немного меньшему байт-коду, так как статические методы не получат доступ к нему
this
. Я не думаю, что это имеет какое-либо значение в скорости (и если это произойдет, то, вероятно, оно будет слишком маленьким, чтобы изменить ситуацию в целом).Я бы сделал их статичными, так как я обычно делаю это, если это вообще возможно. Но это только я.
РЕДАКТИРОВАТЬ: Этот ответ продолжает понижаться, возможно, из-за необоснованного утверждения о размере байт-кода. Так что я на самом деле проведу тест.
Байт-код (получен с помощью
javap -c -private TestBytecodeSize
):Вызов статического метода занимает два байт-кода (byteops?):
iconst_0
(Для аргумента) иinvokestatic
.Вызов нестатического метода занимает три:
aload_1
(дляTestBytecodeSize
объекта, я полагаю),iconst_0
(для аргумента) иinvokespecial
. (Обратите внимание, что если бы это не были частные методы, это было быinvokevirtual
вместоinvokespecial
; см. JLS §7.7 Методы вызова .)Теперь, как я уже сказал, я не ожидаю большой разницы в производительности между этими двумя, за исключением того факта, что
invokestatic
требуется на один байт-код меньше.invokestatic
иinvokespecial
оба должны быть немного быстрее, чемinvokevirtual
, поскольку они оба используют статическое связывание вместо динамического, но я понятия не имею, является ли один из них быстрее, чем другой. Я также не могу найти хорошие ссылки. Самая близкая вещь , которую я могу найти, - это статья JavaWorld 1997 года , которая в основном повторяет то, что я только что сказал:Но многое изменилось с 1997 года.
Итак, в заключение ... Я думаю, что я все еще придерживаюсь того, что я сказал раньше. Скорость не должна быть причиной выбора одного над другим, поскольку в лучшем случае это будет микрооптимизация.
источник
Моим личным предпочтением было бы объявить их статическими, так как это четкий признак того, что они не имеют состояния.
источник
Ответ ... это зависит.
Если member - это переменная экземпляра, специфичная для объекта, с которым вы имеете дело, тогда зачем вообще передавать его как параметр?
Например:
источник
Одна из причин, по которой вы можете объявить статические вспомогательные методы, заключается в том, что вам нужно вызывать их в конструкторе класса «before»
this
илиsuper
. Например:Это немного надуманный пример, но он явно
recoverInt
не может быть методом экземпляра в этом случае.источник
Я не могу придумать явных преимуществ для частного статического метода. Тем не менее, нет никаких особых преимуществ делать их нестатичными. Это в основном вопрос презентации: вы можете сделать их статичными, чтобы четко подчеркнуть тот факт, что они не изменяют объект.
Для метода с разными правами доступа, я думаю, есть два основных аргумента:
Кроме того, разница довольно мала, и я сильно сомневаюсь, что дополнительный указатель this, передаваемый методу экземпляра, имеет существенное значение.
источник
Правильный ответ:
любой метод, который не берет никакой информации из поля и не помещает какую-либо информацию в поле, не должен быть методом экземпляра. Любой метод, который не использует или изменяет какие-либо поля в своем классе или объекте, также может быть статическим методом.
источник
Да.
Сохраняя их как методы экземпляра, вы позволяете себе предоставить другую реализацию позже.
Это может звучать глупо (и на самом деле это было бы так, если бы эти методы использовались только вами в 50-строчной программе), но в более крупных приложениях или в библиотеках, используемых кем-то другим, вы можете решить выбрать лучшую реализацию, но не хочу сломать существующий код.
Таким образом, вы создаете подкласс и возвращаете его в новых версиях, а поскольку методы были объявлены как методы экземпляра, вы просто позволяете полиморфизму выполнять свою работу.
Кроме того, по той же причине вы могли бы выиграть, сделав конструктор частным и предоставив статический метод фабрики.
Поэтому я рекомендую сохранять их как методы экземпляра и по возможности избегать статичности.
Воспользуйтесь динамизмом, который обеспечивает язык.
Смотрите здесь несколько связанных видео: как разработать хороший API и почему это важно
Хотя он не имеет прямого отношения к обсуждению метода «static против экземпляра», он затрагивает некоторые интересные моменты в дизайне API.
источник
Одна из проблем использования статических методов заключается в том, что это может затруднить использование объекта в модульных тестах . Mockito не может создавать насмешки для статических методов, и вы не можете создать реализацию метода подкласса.
источник
Если метод в основном просто подпрограмма, которая никогда не будет использовать информацию о состоянии, объявите ее статической.
Это позволяет использовать его в других статических методах или при инициализации класса, то есть:
источник
Статический / нестатический вопрос сводится к тому, «мне действительно нужно будет использовать объект этого класса»?
Итак, вы передаете объект между различными методами? Содержит ли объект информацию, которая полезна вне контекста статических методов? Есть ли причина не определять методы в обоих направлениях, если вы будете использовать их в обоих направлениях?
Если вы находитесь в этой дилемме, мне кажется, что у вас есть все данные, необходимые для метода, плавающие в вашем коде за пределами объекта. Это то, что вы хотите? Будет ли легче просто всегда собирать эти данные в объект каждый раз? Возможно, вы просто амбивалентно относитесь к одной модели. Если вы можете сделать все это одним способом, тогда выберите статический или нестатический и продолжайте.
источник
Мои предпочтения в таких случаях, чтобы сделать
computeOne
иcomputeMore
статические методы. Причина: инкапсуляция. Чем меньше кода, который имеет доступ к реализации вашего класса, тем лучше.В примере , вы даете, вы заявляете , что
computeOne
иcomputeMore
не нужно доступ внутренностей класса, так зачем давать возможность для автогрейдеров класса вмешиваться с внутренностями.источник
Я хотел бы прояснить несколько вещей, которые другие авторы назвали неправильной информацией.
Во-первых, поскольку методы являются закрытыми, даже если вы объявите их статическими, вы не сможете получить к ним доступ за пределами этого класса. Во-вторых, они являются частными, так что вы не можете даже переопределить в подклассе, чтобы статические или нестатические не имели никакого значения. В-третьих, нестандартный закрытый метод также может быть вызван из конструктора класса, он не обязательно должен быть статическим.
Теперь перейдем к вашему вопросу, должен ли частный вспомогательный метод быть определен как статический или нестатический. Я пойду с ответом Стива, так как пометка статического частного метода показывает, что этот метод не имеет состояния, так как я также следую этому правилу, когда кодирую.
источник
Исходя из опыта, я бы сказал, что такие частные методы имеют тенденцию быть достаточно универсальными и пригодными для повторного использования.
Я думаю, что первое, что нужно сделать, это задать вопрос, может ли метод быть полезным вне контекста текущего класса. Если это так, я бы сделал именно то, что предлагает каждый, и извлек бы этот метод как статический для некоторого класса utils, где, как мы надеемся, кто-то проверяет, прежде чем реализовывать новый метод, делая то же самое.
Такие частные методы общего пользования являются источником большой части дублирования кода в проекте, потому что каждый разработчик самостоятельно заново изобретает их именно там, где ему нужно это использовать. Так что централизация таких методов - это путь.
источник
Более конкретно на примере вы дали, кажется , что цель определения этих методов больше для кода ясности , когда вы читаете это , чем для функциональности (они будут определены как частные). В этом случае использование статического кода на самом деле ничего не делает для вас, поскольку назначение статического кода - показать функциональность класса.
источник
Одна из причин заключается в том, что при прочих равных условиях вызовы статических методов должны выполняться быстрее. Статические методы не могут быть виртуальными и не подразумевают эту ссылку.
источник
Как говорили многие, сделай это как статичный ! Вот правило большого пальца, которому я следую: если вы думаете, что метод - это просто математическая функция, то есть он не содержит состояний, не включает никаких переменных экземпляра (=> нет синего цвета [в затмении] в методе) и результат метод будет таким же для числа вызовов 'n' (с теми же параметрами, конечно), затем отметьте этот метод как STATIC.
И если вы считаете, что этот метод будет полезен для другого класса, в противном случае переместите его в класс Util, в противном случае поместите метод как private в тот же класс. (минимизация доступности)
источник
Не по теме: я бы оставил вспомогательные методы в отдельном классе утилит / помощников, в котором были бы только статические методы.
Проблема с наличием вспомогательных методов в точке их использования (читай «тот же класс») заключается в том, что кто-то в дальнейшем может просто захотеть опубликовать свои собственные несвязанные вспомогательные методы в одном и том же месте.
источник
Преимущество приватных статических методов заключается в том, что они могут быть повторно использованы позже, если вам нужно повторно инициализировать переменную класса.
источник
Без статического модификатора вы не сможете понять, что метод не имеет состояния без дополнительного анализа, который можно легко сделать, когда вы переписываете метод.
Тогда модификатор «static» может дать вам идеи о рефакторинге помимо других вещей, которые другие могут счесть бесполезными. Например, перемещение метода в некоторый класс Utility или преобразование его в метод-член.
источник
Я бы объявил их статическими, чтобы пометить их как не имеющих состояния.
В Java нет лучшего механизма для незначительных операций, которые не экспортируются, поэтому я думаю, что приватная статика приемлема.
источник