99

I've recently been looking through my warnings in Eclipse and come across this one:

static warning

It will give a compiler warning if the method can be declared as static.

[edit] Exact quote within the Eclipse help, with stress on private and final:

When enabled, the compiler will issue an error or a warning for methods which are private or final and which refer only to static members.

Yes I know I can turn it off, but I want to know the reason for turning it on?

Why would it be a good thing to declare every method possible as static?

Will this give any performance benefits? (in a mobile domain)

Pointing out a method as static, I suppose is showing that you don't use any instance variables therefore could be moved to a utils style class?

At the end of the day should I just turn this off 'ignore' or should I fix the 100+ warnings it has given me?

Do you think this is just extra keywords that dirty the code, as the compiler will just inlines these methods anyway? (kind of like you don't declare every variable you can final but you could).

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
Blundell
  • 75,855
  • 30
  • 208
  • 233
  • Unsure but this could simply be seen as a programming aid. Warnings are simply indications of things to look at. – James P. Jun 28 '12 at 07:49
  • 1
    I'm curious as to the kind of functionality these methods perform. Maybe something wasn't done very right if there are so many of these. – ArjunShankar Jun 28 '12 at 07:50
  • Related: http://stackoverflow.com/q/790281 – Brian Rasmussen Jul 03 '12 at 16:47
  • I had a similar question and none of the comments really eloquently said the answer. Private makes methods inaccessible to other classes (even if you extend). Static allows you to make methods that will not change (are finalized). So if you want to give methods to another class but don't want them to change, make it a public static method. If you are accepting inputs as args, you DON'T make it static. – Evan Erickson Dec 21 '21 at 18:10
  • Also, if a method is static, you can just reference it with methodName(); in your new class that is extending the old class. You don’t need to put className.methodName() like you do with non static methods. – Evan Erickson Dec 21 '21 at 18:10

9 Answers9

142

Whenever you write a method, you fulfill a contract in a given scope. The narrower the scope is, the smaller the chance is that you write a bug.

When a method is static, you can't access non-static members; hence, your scope is narrower. So, if you don't need and will never need (even in subclasses) non-static members to fulfill your contract, why give access to these fields to your method? Declaring the method static in this case will let the compiler check that you don't use members that you do not intend to use.

And moreover, it will help people reading your code understand the nature of the contract.

That's why it's considered good to declare a method static when it's actually implementing a static contract.

In some cases, your method only means something relative to an instance of your class, and it happens that its implementation doesn't actually use any non-static field or instance. In such cases, you would not mark the method static.

Examples of where you would not use the static keyword:

  • An extension hook which does nothing (but could do something with instance data in a subclass)
  • A very simple default behavior meant to be customisable in a subclass.
  • Event handler implementation: implementation will vary with the class of the event handler but will not use any property of the event handler instance.
Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
Samuel Rossille
  • 18,940
  • 18
  • 62
  • 90
  • 1
    +1 Its about minimising the opportunities to shoot yourself in the foot, and reducing how much you need to know to understand a method. – Peter Lawrey Jun 28 '12 at 07:52
  • 7
    Plus, you don't need to fiddle with acquiring an instance just to call an independent, self-contained function. – Marko Topolnik Jun 28 '12 at 07:56
  • 1
    So in other worlds, any method which is not using instance variables should be declared as static?I always thought that methods should be static only if it's desirable (like utitility methods). – Petr Mensik Jun 28 '12 at 08:18
  • 18
    @PetrMensik If a `private` method could be declared static, then almost invariably it **should** be. For any other access level, there are other factors to consider, like dynamic dispatch. – Marko Topolnik Jun 28 '12 at 08:19
  • @MarkoTopolnik What do you mean by dynamic dispatch? – James P. Jun 28 '12 at 09:59
  • 1
    @JamesPoulson I mean dynamic method dispatch, the thing happening while exetucing `object.method()` to select the method to call. – Marko Topolnik Jun 28 '12 at 10:03
  • 1
    I think you need to make a distinction here; if you expect that you will ever need an instance variable in a future version, you *should not* make the method static, and ignore the warning (or your design will change because of an implementation issue). I've turned it off myself, I am a better judge (by now) if a method should be `static` or not. – Maarten Bodewes Jun 29 '12 at 00:10
  • @owlstead declaring it `static` is informing other developers of the contract between this method and the class. If someone in the future wanted to *change the code* and use an instance variable. Then they can remove the `static` declaration and in removing it they will know they've changed the contract (and therefore thinking about all that entails) – Blundell Jul 03 '12 at 12:07
  • 1
    @Blundell I don't agree. Say you have a `getVersion()` method, and a constant 1 which is always returned. Then you update the class to handle two versions. Now `getVersion()` should suddenly be not static anymore? I think just looking at field access is forgetting the semantics of the method. – Maarten Bodewes Jul 03 '12 at 16:02
  • 1
    @owlstead I don't get what *handle two versions* infers but if your `getVersion()` took an input (say some system config) it would stay static, but I don't see the problem with changing it two non-static in the scenario you described. *We're allowed to change things :)* – Blundell Jul 03 '12 at 18:15
  • @Blundell: No, contracts should stay as static as possibly can, unless they *require* a rewrite/refactoring. Refactoring will mean rewriting/refactoring other classes, and possiblty test cases etc. Besides, there is no programming argument by being semantically wrong. – Maarten Bodewes Jul 03 '12 at 19:07
  • 1
    @owlstead aren't you mixing up `public static` and `private static`. We are talking about `private static` where other classes aren't involved – Blundell Jul 03 '12 at 19:54
  • @Blundell looked it up in Eclipse. It's actuall **`private`** or **`final`**. I can see no problem with `private` methods. `final` is another matter as those methods may still be used by other classes, so you would have to break the contract if you change them. Added exact description from Eclipse to question. Subclassing is safe from issues though. – Maarten Bodewes Jul 03 '12 at 23:29
  • @BenMosher: subclassing is not an issue as the method in Eclipse will have to be `private` or `final` for the warning to be issued, added this to description within question – Maarten Bodewes Jul 03 '12 at 23:33
  • @MarkoTopolnik As far as could get from the discussion, we use static methods basically if it's either a private helper method or a static factory method. Did I get it right? – St.Antario Jul 20 '15 at 08:26
  • @St.Antario There are many more use cases than that. Any pure function is a candidate for a static method, but not only pure functions. – Marko Topolnik Jul 20 '15 at 08:32
  • @MarkoTopolnik Thanks, but we definitely __should__ declare a function static in the two cases I mentioned, right? – St.Antario Jul 20 '15 at 08:35
  • I don't know what exactly rules you assume behind that "should". A private method may or may not be static, it'll work both ways. It will be easier to read/maintain if it's static. A factory method cannot possibly be non-static if it provides objects of the class it resides in, so that's a much stronger "should". – Marko Topolnik Jul 20 '15 at 08:48
17

There is no concept with optimization here.

A static method is static because you explicitly declare that method doesn't rely on any instance the enclosing class just because it doesn't need to. So that Eclipse warning, as stated in documentation:

When enabled, the compiler will issue an error or a warning for methods which are private or final and which refer only to static members.

If you don't need any instance variable and your method is private (can't be called from outside) or final (can't be overriden) then there is no reason to let it be a normal method instead that a static one. A static method is inherently safer even just because you are allowed to do less things with it (it doesn't need any instance, you don't have any implicit this object).

PSR
  • 39,804
  • 41
  • 111
  • 151
Jack
  • 131,802
  • 30
  • 241
  • 343
7

I've no info on the performance, I suppose it is marginally better at most, since the code does not need to do dynamic dispatch based on the type.

However, a much stronger argument against refactoring into static methods is that currently using static is considered bad practice. Static methods / variables do not integrate well into an object oriented language and also, hard to test properly. This is the reason why some newer languages forego the concept of static methods/variables altogether, or try to internalize it into the language in a way that plays better with OO (eg Objects in Scala).

Most of the time, you need static methods to implement functions that are only using parameters as an input and producing an output using that (eg utility/helper functions) In modern languages, there is a first class Function concept that allows that, so static is not needed. Java 8 will have lambda expressions integrated, so we are moving into this direction already.

Istvan Devai
  • 3,962
  • 23
  • 21
  • 7
    Static methods are trivial to test (as long as they are self-contained---especially pure functions, which are the primary target for a static method). The OO concept has nothing to offer in that case. Also, the concept of a first-class function has very little, if anything, to do with the concept of a static method. If you ever need a first-class function that does the work of an existing static method, it is a matter of a handful of characters to implement it. – Marko Topolnik Jun 28 '12 at 10:21
  • 5
    The testability remark was probably not geared towards the static method directly, but static methods are much more difficult to mock, so they complicate testing of methods that call static methods. – Buhb Jun 28 '12 at 10:32
  • 2
    Static methods are easy to mock if you use a powerful mocking framework like [JMockit](http://code.google.com/p/jmockit/), [PowerMock](http://code.google.com/p/powermock/), or [Groovy](http://groovy.codehaus.org/Mocking+Static+Methods+using+Groovy). – Jeff Olson Jul 06 '12 at 03:24
  • These are `private static` methods so you won't be needing to mock them – Blundell Jul 09 '12 at 20:45
3

1. Declaring method static gives slight performance benefit, but what is more useful, it allows using it without having an object instance at hand (think of for example about factory method or getting a singleton). It also serves the documentational purpose of telling the nature of the method. This documentational purpose should not be ignored, as it gives immediate hint about the nature of the method to the readers of the code and users of the API and also serves as a tool of thinking for the original programmer - being explicit about the intended meaning helps you also think straight and produce better quality code (I think based on my personal experience, but people are different). For example, it is logical and hence desirable to distinguish between methods operating on a type and methods acting on an instance of the type (as pointed out by Jon Skeet in his comment to a C# question).

Yet another use case for static methods is to mimic procedural programming interface. Think of java.lang.System.println() class and the methods and attributes therein. The class java.lang.System is used like a grouping name space rather than an instantiable object.

2. How can Eclipse (or any other programmed or other kind of - biocomposable or non-biocomposable - entity) know for sure which method could be declared as static? Even if a base class is not accessing instance variables or calling non-static methods, by the mechanism of inheritance the things can change. Only if the method cannot be overridden by inheriting subclass, can we claim with 100% certainty that the method really can be declared static. Overriding a method is impossible exactly in the two cases of being

  1. private (no subclass can use it directly and does not even in principle know about it), or
  2. final (even if accessible by the subclass, there is no way to change the method to refer to instance data or functions).

Hence the logic of the Eclipse option.

3. The original poster also asks: "Pointing out a method as static, I suppose is showing that you don't use any instance variables therefore could be moved to a utils style class?" This is a very good point. Sometimes this kind of design change is indicated by the warning.

It is very useful an option, which I would personally make sure to enable, were I to use Eclipse and were I to program in Java.

Community
  • 1
  • 1
FooF
  • 4,323
  • 2
  • 31
  • 47
1

See Samuel's answer on how the scope of the method changes. I guess, this is the main aspect of making a method static.

You also asked about performance:

There might be a tiny performance gain, because a call to a static method does not need the implicit "this" reference as parameter.

However, this performance impact is really tiny. Therefore, it's all about the scope.

Black
  • 5,022
  • 2
  • 22
  • 37
1

From the Android Performance guidelines:

Prefer Static Over Virtual If you don't need to access an object's fields, make your method static. Invocations will be about 15%-20% faster. It's also good practice, because you can tell from the method signature that calling the method can't alter the object's state.

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

Blundell
  • 75,855
  • 30
  • 208
  • 233
  • "that calling the method can't alter the object's state" -- is incredibly misleading. I don't know about you, but I certainly consider static attributes of a class to be a part of an object's state. – Adam Parkin Apr 04 '14 at 21:29
0

Well, the Eclipse documentation says about the warning in question:

Method can be static

When enabled, the compiler will issue an error or a warning for methods which are private or final and which refer only to static members

I think it pretty much says it all. If the method is private and final and only refers to static members, the method in question might just as well be declared static and by this, make evident that we only intend to access static content from it.

I honestly don't think there is any other mysterious reason behind it.

Edwin Dalorzo
  • 76,803
  • 25
  • 144
  • 205
0

I was missing some numbers for the speed differences. So I tried to benchmark them which turned out to be not so easy: Java loop gets slower after some runs / JIT's fault?

I finally used Caliper and the results are the same as running my tests by hand:

There is no measurable difference for static/dynamic calls. At least not for Linux/AMD64/Java7.

The Caliper Results are here: 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

and my own results are:

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

The Caliper Test class was:

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;
    }

}

And my own Test class was:

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;
    }

}
Scheintod
  • 7,953
  • 9
  • 42
  • 61
  • would be interesting to see the results on various android devices and versions – Blundell Jul 22 '14 at 23:23
  • Yea. I thought that you would be interested :) But since you are building android software and probably have an android device laying around connected to your dev station I suggest you just pick the code , run it and share the results? – Scheintod Jul 22 '14 at 23:29
-2

The methods you can declare as static are the ones that don't require instantiation, such as

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

Which you can then in return call out in any other class without instanciating that class.

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

... But that's something you probably already know. It doesn't give you any real benefits per se, other than making it more clear that the method doesn't use any instance variables.

In other words, you can most safely just turn it off completely. If you know you will never use a method in other classes (in which case it should just be private), you don't need it to be static at all.

NeroS
  • 1,179
  • 1
  • 12
  • 28