Should private helper methods be static if they can be static

JavaStaticMethodsStatic Methods

Java Problem Overview


Let's say I have a class designed to be instantiated. I have several private "helper" methods inside the class that do not require access to any of the class members, and operate solely on their arguments, returning a result.

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) {... } 
} 

Is there any particular reason to specify computeOne and computeMore as static methods - or any particular reason not to?

It is certainly easiest to leave them as non-static, even though they could certainly be static without causing any problems.

Java Solutions


Solution 1 - Java

I prefer such helper methods to be private static; which will make it clear to the reader that they will not modify the state of the object. My IDE will also show calls to static methods in italics, so I will know the method is static without looking the signature.

Solution 2 - Java

It might result in slightly smaller bytecode, since the static methods won't get access to this. I don't think it makes any difference in speed (and if it did, it would probably be too small to make a difference overall).

I would make them static, since I generally do so if at all possible. But that's just me.


EDIT: This answer keeps getting downvoted, possibly because of the unsubstantiated assertion about bytecode size. So I will actually run a test.

class TestBytecodeSize {
    private void doSomething(int arg) { }
    private static void doSomethingStatic(int arg) { }
    public static void main(String[] args) {
        // do it twice both ways
        doSomethingStatic(0);
        doSomethingStatic(0);
        TestBytecodeSize t = new TestBytecodeSize();
        t.doSomething(0);
        t.doSomething(0);
    }
}

Bytecode (retrieved with javap -c -private TestBytecodeSize):

Compiled from "TestBytecodeSize.java"
class TestBytecodeSize extends java.lang.Object{
TestBytecodeSize();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

private void doSomething(int);
  Code:
   0:   return

private static void doSomethingStatic(int);
  Code:
   0:   return

public static void main(java.lang.String[]);
  Code:
   0:   iconst_0
   1:   invokestatic    #2; //Method doSomethingStatic:(I)V
   4:   iconst_0
   5:   invokestatic    #2; //Method doSomethingStatic:(I)V
   8:   new     #3; //class TestBytecodeSize
   11:  dup
   12:  invokespecial   #4; //Method "<init>":()V
   15:  astore_1
   16:  aload_1
   17:  iconst_0
   18:  invokespecial   #5; //Method doSomething:(I)V
   21:  aload_1
   22:  iconst_0
   23:  invokespecial   #5; //Method doSomething:(I)V
   26:  return

}

Invoking the static method takes two bytecodes (byteops?): iconst_0 (for the argument) and invokestatic.
Invoking the non-static method takes three: aload_1 (for the TestBytecodeSize object, I suppose), iconst_0 (for the argument), and invokespecial. (Note that if these hadn't been private methods, it would have been invokevirtual instead of invokespecial; see JLS §7.7 Invoking Methods.)

Now, as I said, I don't expect there to be any great difference in performance between these two, other than the fact that invokestatic requires one fewer bytecode. invokestatic and invokespecial should both be slightly faster than invokevirtual, since they both use static binding instead of dynamic, but I have no idea if either is faster than the other. I can't find any good references either. The closest I can find is this 1997 JavaWorld article, which basically restates what I just said: >The fastest instructions will most likely be invokespecial and invokestatic, because methods invoked by these instructions are statically bound. When the JVM resolves the symbolic reference for these instructions and replaces it with a direct reference, that direct reference probably will include a pointer to the actual bytecodes.

But many things have changed since 1997.

So in conclusion... I guess I'm still sticking with what I said before. Speed shouldn't be the reason to choose one over the other, since it would be a micro-optimization at best.

Solution 3 - Java

My personal preference would be to declare them static, as it's a clear flag that they're stateless.

Solution 4 - Java

The answer is... it depends.

If member is an instance variable specific to the object you're dealing with, then why pass it as a parameter at all?

For instance:

public class Example {
   private Something member;

   public double compute() {
       double total = 0;
       total += computeOne();
       total += computeMore();
       return total;         
   }

   private double computeOne() { /* Process member here */ }
   private double computeMore() { /* Process member here */ } 
}

Solution 5 - Java

One reason you might want to declare static helper methods is if you need to call them in the class constructor "before" this or super. For example:

public class MyClass extends SomeOtherClass { 
    public MyClass(String arg) {
       super(recoverInt(arg));
    }

    private static int recoverInt(String arg) {
       return Integer.parseInt(arg.substring(arg.length() - 1));
    }
}

This is a bit of a contrived example but clearly recoverInt cannot be an instance method in this case.

Solution 6 - Java

I can't really think of clear advantages for private static method. That being said, there is no specific advantages to making them non-static either. It's mainly a matter of presentation : you might want to make them static to clearly underline the fact that they are not altering an object.

For method with different access privileges, I think there are two main arguments :

  • static methods can be called without creating an instance of an object, which can be useful
  • static methods can't be inherited, which can be a problem if you need polymorphism (but is irrelevant for private methods).

Besides that, the difference is pretty small, and I strongly doubt that the extra this pointer passed to instance method makes a significant difference.

Solution 7 - Java

Correct Answer is:

any method which does not take any information from a field, and does not put any information into a field, does not have to be an instance method. Any method which does not use or alter any fields in its class or object might as well be a static method.

Solution 8 - Java

>or any particular reason not to [declare them as static]?

Yes.

By keeping them as instance methods, you allow yourself to provide a different implementation later.

It may sound silly (and actually it would be if those methods are used only by you in a 50 line program) but in larger applications, or in libraries used by someone else, you may decide to choose a better implementation, but don't want to break existing code.

So you create a subclass and return that in the new versions, and since the methods were declared as instance methods, you just let polymorphism do its job.

Additionally, you could benefit from making the constructor private and provide an static factory method for the same reason.

So, my recommendation is to keep them as instance methods, and avoid static if possible.
Take advantage of the dynamism the language provides.

See here for a somewhat related video: How to design a good API and why it matters

Although it is not directly related to the "static vs instance" method discussion, it touches on some interesting points in API design.

Solution 9 - Java

If the method is basically just a subroutine that will never foreseeably use state information, declare it static.

This allows it to be used in other static methods or in class initialization, i.e.:

public class Example {
   //...
   
   //Only possible if computeOne is static
   public final static double COMPUTED_ONE = computeOne(new Something("1"));
   
   //...
}

Solution 10 - Java

One issue about having static methods is that it can make the object more difficult to use in unit tests. Mockito can't create mocks for static methods and you can't create a subclass implementation of the method.

Solution 11 - Java

The static/non-static question comes down to "will I really need to use an object of this class"?

So, are you passing the object between different methods? Does the object contain information that is useful outside the context of the static methods? Is there any reason not to define methods both ways if you'll use them both ways?

If you're in this dilemma, it seems to me that you have all of the data required for the method floating around in your code outside of the object. Is this what you want? Would it be easier to just always collect that data into an object each time? You might just be ambivalent about committing to a single model. If you can do it all using one way, then pick either static or non-static and go with it.

Solution 12 - Java

My preference in cases like these is to make computeOne and computeMore static methods. The reason: encapsulation. The less code which has access to the implementation of your class, the better.

In the example you give, you state that computeOneand computeMore shouldn't need to access the internals of the class, so why give the opportunity for maintainers of the class to meddle with the internals.

Solution 13 - Java

I would like to clarify few things which other posters have said as its giving wrong information.

Firstly since the methods are private even if you declare them static you will not be able to access them outside of this class. Secondly they are private so you can not even override in subclass so static or non-static doesn't make any difference. Thirdly a non-static private method can be called from a constructor of the class also, it need not be static.

Now coming to your question if a private helper method should be defined as static or non-static. I will go with Steve's answer as marking a private method static shows that this method is stateless as I also follow this rule when I code.

Solution 14 - Java

From the experience I would state that such private methods tend to be quite universal and reusable.

I think the first thing to do is to ask the question whether the method may be useful outside of current class context. If so, I would do exactly what Everyone suggests and extract this method as static to some utils class where someone hopefully checks before implementing new method doing exactly the same thing.

Such general use private methods are source of big part of code duplication in project because each developer independently reinvents them just in the place she need to use it. So centralization of such methods is a way to go.

Solution 15 - Java

More specifically to the example you've given, it seems that the purpose of defining these methods is more for code clarity when you're reading it than for functionality (they are defined as private). In that case, going with static really does nothing for you, since the purpose of static is to expose class functionality.

Solution 16 - Java

One reason is that, all else being equal, static method calls should be faster. Static methods cannot be virtual, and do not take an implicit this reference.

Solution 17 - Java

As many people said, make it is as a static! Here's the thumb rule which I follow : If you think the method is just a mathematical function i.e it is stateless, doesn't involve any instance variables(=> no blue color vars [in eclipse] in the method), and the result of the method will be the same for 'n' number of calls (with the same parameters, ofcourse), then mark that method as STATIC.

And if you think that this method will be useful to other class then move it to a Util class otherwise, put the method as private in the sameclass. (minimizing the accessibility)

Solution 18 - Java

Off-Topic: I'd keep the helper methods in a standalone utility/helper class with only static methods in it.

The trouble with having helper methods at the point of use ( read 'same class' ) is that someone down the line may just choose to post their own unrelated helper methods in the same place

Solution 19 - Java

class Whatever {
    
    public static varType myVar = initializeClassVariable();
	
    private static varType initializeClassVariable() {

        //initialization code goes here
    }
}

The advantage of private static methods is that they can be reused later if you need to reinitialize the class variable.

Solution 20 - Java

  1. Without the static modifier you cannot figure out that the method is stateless without additional analysis which can be easily done when you (re)write the method.

  2. Then "static" modifier may give you ideas about refactoring besides other things that others may find unuseful. E.g. moving the method to some Utility class or converting it to a member method..

Solution 21 - Java

I would declare them as static to flag them as stateless.

Java does not have a better mechanism for minor operations that aren't exported, so I think private static is acceptable.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionavalysView Question on Stackoverflow
Solution 1 - JavaEsko LuontolaView Answer on Stackoverflow
Solution 2 - JavaMichael MyersView Answer on Stackoverflow
Solution 3 - JavaSteve B.View Answer on Stackoverflow
Solution 4 - JavaPowerlordView Answer on Stackoverflow
Solution 5 - Javaoxbow_lakesView Answer on Stackoverflow
Solution 6 - JavaAxelle ZieglerView Answer on Stackoverflow
Solution 7 - JavaGyan SinghView Answer on Stackoverflow
Solution 8 - JavaOscarRyzView Answer on Stackoverflow
Solution 9 - JavaKipView Answer on Stackoverflow
Solution 10 - JavaJon OnstottView Answer on Stackoverflow
Solution 11 - JavanotnotView Answer on Stackoverflow
Solution 12 - JavamaxaposterioriView Answer on Stackoverflow
Solution 13 - JavaBhushan BhangaleView Answer on Stackoverflow
Solution 14 - JavaPiotr SobczykView Answer on Stackoverflow
Solution 15 - JavanotnotView Answer on Stackoverflow
Solution 16 - JavadsimchaView Answer on Stackoverflow
Solution 17 - JavajaiView Answer on Stackoverflow
Solution 18 - JavaEveryoneView Answer on Stackoverflow
Solution 19 - Javamug896View Answer on Stackoverflow
Solution 20 - JavabodrinView Answer on Stackoverflow
Solution 21 - JavaUriView Answer on Stackoverflow