Каков выигрыш от объявления метода как статического

Недавно я просматривал свои предупреждения в Eclipse и сталкивался с этим:

статическое предупреждение

Это даст предупреждение компилятору, если метод может быть объявлен как статический.

[править] Точная цитата из справки Eclipse, с акцентом на частных и окончательных:

Когда включено, компилятор выдаст ошибку или предупреждение для методов, которые являются частными или окончательными и относятся только к статическим членам.

Да, я знаю, что могу отключить его, но я хочу знать причину его включения?

Почему было бы хорошо объявить каждый способ возможным как статический?

Приведет ли это какое-либо преимущество в производительности? (в мобильном домене)

Указывая метод как статический, я предполагаю, что вы не используете какие-либо переменные экземпляра, поэтому его можно перенести в class стиля utils?

В конце дня я должен просто отключить это «игнорировать» или исправить 100+ предупреждений, которые он дал мне?

Считаете ли вы, что это просто лишние ключевые слова, которые загрязняют код, поскольку компилятор просто вставляет эти методы в любом случае? (вроде как вы не объявляете, что каждая переменная вы можете окончательно, но можете ).

Всякий раз, когда вы пишете метод, вы выполняете контракт в заданной области. Чем меньше область охвата, тем меньше вероятность того, что вы напишете ошибку.

Когда метод статичен, вы не можете получить доступ к нестационарным членам; следовательно, ваш объем уже. Итак, если вам не нужны и не нужны (даже в подclassах) нестатические члены для выполнения вашего контракта, зачем предоставлять доступ к этим полям вашему методу? Объявление static метода в этом случае позволит компилятору проверить, что вы не используете членов, которые вы не собираетесь использовать.

И более того, это поможет людям, читающим ваш код, понять природу контракта.

Вот почему считается хорошим объявить метод static когда он фактически реализует статический контракт.

В некоторых случаях ваш метод означает только что-то относительно экземпляра вашего classа, и бывает так, что его реализация фактически не использует какое-либо нестатическое поле или экземпляр. В таких случаях вы не ставите знак static .

Примеры того, где вы не будете использовать static ключевое слово:

  • Крючок расширения, который ничего не делает (но может делать что-то с данными экземпляра в подclassе)
  • Очень простое поведение по умолчанию, которое должно настраиваться в подclassе.
  • Реализация обработчика события: реализация будет отличаться от classа обработчика события, но не будет использовать какое-либо свойство экземпляра обработчика события.

Здесь нет концепции оптимизации.

static метод static потому что вы явно объявляете, что этот метод не полагается на какой-либо экземпляр окружающего classа только потому, что ему это не нужно. Так что предупреждение Eclipse, как указано в документации:

Когда включено, компилятор выдаст ошибку или предупреждение для методов, которые являются частными или окончательными и относятся только к статическим членам.

Если вам не нужна переменная экземпляра, и ваш метод является закрытым (не может быть вызван извне) или final (нельзя переопределить), тогда нет оснований позволять ему быть обычным способом, а не статическим. Статический метод по своей сути более безопасен даже потому, что вам разрешено делать с ним меньше дел (ему не нужен какой-либо экземпляр, у вас нет какого-либо неявного this объекта).

У меня нет информации о производительности, я полагаю, что это немного лучше, поскольку код не требует динамической отправки на основе этого типа.

Тем не менее, гораздо более сильный аргумент против рефакторинга в статические методы заключается в том, что в настоящее время использование статики считается плохой практикой. Статические методы / переменные не очень хорошо интегрируются в объектно-ориентированный язык, а также трудно проверить правильно. Именно по этой причине некоторые новые языки вообще отказываются от концепции статических методов / переменных или пытаются усвоить ее на языке таким образом, который лучше работает с OO (например, объекты в Scala).

В большинстве случаев вам понадобятся статические методы для реализации функций, которые используют только параметры в качестве входных данных и выводят их с использованием (например, служебные / вспомогательные функции). В современных языках существует концепция classа первого classа, которая позволяет так статично не требуется. Java 8 будет иметь интегрированные lambda-выражения, поэтому мы уже движемся в этом направлении.

1. Объявление метода static дает небольшое преимущество в производительности, но, что более полезно, оно позволяет использовать его без наличия экземпляра объекта (например, о методе фабрики или получении синглета). Он также служит документальной цели, чтобы рассказать о характере метода. Эта документальная цель не следует игнорировать, поскольку она дает немедленный намек на характер метода читателям кода и пользователей API, а также служит инструментом мышления для оригинального программиста – явным образом о предполагаемом значении помогает вы также считаете, что прямо и производят код лучшего качества (я думаю, основываясь на моем личном опыте, но люди разные). Например, логично и, следовательно, желательно различать методы, действующие на тип и методы, действующие на экземпляр типа (как указал Джон Скит в своем комментарии к вопросу C # ).

Еще одним вариантом использования static методов является имитация процедурного интерфейса программирования. Подумайте о classе java.lang.System.println() и методах и атрибутах в нем. Класс java.lang.System используется как пространство имен групп, а не объект-объект.

2. Как может Eclipse (или любой другой запрограммированный или другой вид – биоразлагаемый или не-биокомпозиционный объект) точно знать, какой метод может быть объявлен как статический? Даже если базовый class не обращается к переменным экземпляра или вызывает нестатические методы, механизм наследования может измениться. Только если метод не может быть переопределен путем наследования подclassа, можем ли мы заявить со 100% уверенностью, что метод действительно может быть объявлен static . Переопределение метода невозможно в двух случаях:

  1. private (никакой подclass не может использовать его напрямую и даже не знает об этом вообще), или
  2. final (даже если он доступен подclassом, нет способа изменить метод для обращения к данным или функциям экземпляра).

Отсюда логика опции Eclipse.

3. Оригинальный плакат также спрашивает: « Указав метод как статический, я полагаю, что вы не используете какие-либо переменные экземпляра, поэтому его можно перенести в class стиля utils? » Это очень хороший момент. Предупреждение. Такое изменение дизайна указывается предупреждением.

Это очень полезный вариант, который я лично должен был бы обязательно включить, если бы я использовал Eclipse и должен ли я программировать на Java.

См. Ответ Сэмюэя о том, как изменяется масштаб метода. На мой взгляд, это основной аспект создания статического метода.

Вы также спросили о производительности:

Может быть крошечное усиление производительности, потому что вызов статического метода не нуждается в неявной «этой» ссылке в качестве параметра.

Однако это влияние производительности очень мало. Поэтому все дело в сфере.

Из рекомендаций по производительности Android:

Предпочитаете статический виртуальный Если вам не нужно обращаться к полям объекта, сделайте свой метод статическим. Вызовы будут примерно на 15-20% быстрее. Это также хорошая практика, потому что вы можете сказать по сигнатуре метода, что вызов метода не может изменить состояние объекта.

http://developer.android.com/training/articles/perf-tips.html#PreferStatic

Ну, в документации Eclipse говорится об этом предупреждении:

Метод может быть статическим

Когда включено, компилятор выдаст ошибку или предупреждение для методов, которые являются частными или окончательными и которые относятся только к статическим членам

Я думаю, это в значительной степени говорит обо всем. Если этот метод является частным и конечным и относится только к статическим членам, рассматриваемый метод может быть также объявлен статическим, и этим мы сделаем очевидным, что мы только хотим получить от него статический контент.

Я честно не думаю, что есть какая-то другая таинственная причина.

Мне не хватало некоторых цифр для разницы в скорости. Поэтому я попытался сравнить их, что оказалось не так просто: цикл Java становится медленнее после некоторых прогонов / ошибок JIT?

Я, наконец, использовал Caliper, и результаты совпадают с результатами моих тестов вручную:

Не существует измеримой разницы для статических / динамических вызовов. По крайней мере, не для Linux / AMD64 / Java7.

Результаты калибровки приведены здесь: https://microbenchmarks.appspot.com/runs/1426eac9-36ca-48f0-980f-0106af064e8f#r:scenario.benchmarkSpec.methodName,scenario.vmSpec.options.CMSLargeCoalSurplusPercent,scenario.vmSpec.options. CMSLargeSplitSurplusPercent, scenario.vmSpec.options.CMSSmallCoalSurplusPercent, scenario.vmSpec.options.CMSSmallSplitSurplusPercent, scenario.vmSpec.options.FLSLargestBlockCoalesceProximity, scenario.vmSpec.options.G1ConcMarkStepDurationMillis

и мои собственные результаты:

 Static: 352 ms Dynamic: 353 ms Static: 348 ms Dynamic: 349 ms Static: 349 ms Dynamic: 348 ms Static: 349 ms Dynamic: 344 ms 

Класс испытания суппорта был:

 public class TestPerfomanceOfStaticMethodsCaliper extends Benchmark { public static void main( String [] args ){ CaliperMain.main( TestPerfomanceOfStaticMethodsCaliper.class, args ); } public int timeAddDynamic( long reps ){ int r=0; for( int i = 0; i < reps; i++ ) { r |= addDynamic( 1, i ); } return r; } public int timeAddStatic( long reps ){ int r=0; for( int i = 0; i < reps; i++ ) { r |= addStatic( 1, i ); } return r; } public int addDynamic( int a, int b ){ return a+b; } private static int addStatic( int a, int b ){ return a+b; } } 

И мой собственный тестовый class:

 public class TestPerformanceOfStaticVsDynamicCalls { private static final int RUNS = 1_000_000_000; public static void main( String [] args ) throws Exception{ new TestPerformanceOfStaticVsDynamicCalls().run(); } private void run(){ int r=0; long start, end; for( int loop = 0; loop<10; loop++ ){ // Benchmark start = System.currentTimeMillis(); for( int i = 0; i < RUNS; i++ ) { r += addStatic( 1, i ); } end = System.currentTimeMillis(); System.out.println( "Static: " + ( end - start ) + " ms" ); start = System.currentTimeMillis(); for( int i = 0; i < RUNS; i++ ) { r += addDynamic( 1, i ); } end = System.currentTimeMillis(); System.out.println( "Dynamic: " + ( end - start ) + " ms" ); // Do something with r to keep compiler happy System.out.println( r ); } } private int addDynamic( int a, int b ){ return a+b; } private static int addStatic( int a, int b ){ return a+b; } } 

Методы, которые вы можете объявить как статические, – это те, которые не требуют создания экземпляра, например

 public class MyClass { public static string InvertText(string text) { return text.Invert(); } } 

Затем вы можете в любом случае вызвать вызов в любом другом classе, не инициируя этот class.

 public class MyClassTwo { public void DoSomething() { var text = "hello world"; Console.Write(MyClass.InvertText(text)); } } 

… Но это то, что вы, наверное, уже знаете. Это не дает вам каких-либо реальных преимуществ как таковых, кроме как более ясно, что метод не использует никаких переменных экземпляра.

Другими словами, вы можете безопасно просто полностью отключить его. Если вы знаете, что никогда не будете использовать метод в других classах (в этом случае он должен быть только частным), вам не нужно, чтобы он был статичным вообще.

  • Эффективное умножение векторных матриц 4x4 на SSE: горизонтальное добавление и точечный продукт - в чем смысл?
  • Что лучше ? Несколько операторов if, или один, если с несколькими условиями
  • для оптимизации цикла
  • Как эффективно удалять дубликаты из массива без использования Set
  • в то время как (1) Vs. for (;;) Есть ли разница в скорости?
  • Перемещает бит быстрее, чем умножение и деление на Java? .СЕТЬ?
  • C # оптимизирует конкатенацию строковых литералов?
  • Proguard с OrmLite на Android
  • Почему mulss занимает всего 3 цикла на Хасуэлле, отличном от таблиц инструкций Агнера?
  • Java Integer compareTo () - зачем использовать сравнение или вычитание?
  • Что такое копирование и как он оптимизирует идиому копирования и свопинга?
  • Давайте будем гением компьютера.