Should Private Helper Methods Be Static If They Can Be Static

Should private helper methods be static if they can be static

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.

Private helper methods vs. public static utility methods in Java

"Wrong" mindset here.

You do not rework your classes because tools are complaining about this or that.

You want to improve the quality of your source code; and such tools can help with identifying "topics worth thinking think about". You take their feedback as hint; not as "order".

Therefore you don't worry about "lines of code" within a class. Instead, you worry about the responsibilities that this class has. Meaning: the line number count isn't a problem per se - but violations of the Single Responsibility Principle are.

Thus: you step back and check out what exactly your class is doing. And when it is clearly doing more than one thing, you extract such aspects into other classes!

Meaning: if you actually find that all this code "belongs" to the responsibility of that class; then keep it in there. Don't start putting internal implementation details into unrelated helper classes; just because some tool warns you about number of lines.

On the other hand, turning private methods into something that is static/package protected would allow you to unit test those methods. Which could be an advantage. But as said: as long as we are talking about implementation details, they should stay private; and they shouldn't be unit tested anyway.

Long story code: know and understand what "clean code" is about; and try to follow the ideas outlined there.

Why would you not use static methods for all private methods?

Static methods cannot access the non-static member data in the class.

Should my helper methods use Static classes in C#

You should make them static to avoid wasting memory on class instances.

In general, any method that does not depend on the state of an instance should be static.

Helper classes that contain nothing but static methods should themselves be declared static to prevent you from accidentally adding non-static members and from instantiating the classes.

Should Java methods be static by default?

To answer the question on the title, in general, Java methods should not be static by default. Java is an object-oriented language.

However, what you talk about is a bit different. You talk specifically of helper methods.

In the case of helper methods that just take values as parameters and return a value, without accessing state, they should be static. Private and static. Let me emphasize it:

Helper methods that do not access state should be static.



1. Major advantage: the code is more expressive.

Making those methods static has at least a major advantage: you make it totally explicit in the code that the method does not need to know any instance state.

The code speaks for itself. Things become more obvious for other people that will read your code, and even for you in some point in the future.

2. Another advantage: the code can be simpler to reason about.

If you make sure the method does not depend on external or global state, then it is a pure function, ie, a function in the mathematical sense: for the same input, you can be certain to obtain always the same output.

3. Optimization advantages

If the method is static and is a pure function, then in some cases it could be memoized to obtain some performance gains (in change of using more memory).

4. Bytecode-level differences

At the bytecode level, if you declare the helper method as an instance method or as a static method, you obtain two completely different things.

To help make this section easier to understand, let's use an example:

public class App {
public static void main(String[] args) {
WithoutStaticMethods without = new WithoutStaticMethods();
without.setValue(1);
without.calculate();

WithStaticMethods with = new WithStaticMethods();
with.setValue(1);
with.calculate();
}
}

class WithoutStaticMethods {

private int value;

private int helper(int a, int b) {
return a * b + 1;
}

public int getValue() {
return value;
}

public void setValue(int value) {
this.value = value;
}

public int calculate() {
return helper(value, 2 * value);
}
}

class WithStaticMethods {

private int value;

private static int helper(int a, int b) {
return a * b + 1;
}

public int getValue() {
return value;
}

public void setValue(int value) {
this.value = value;
}

public int calculate() {
return helper(value, 2 * value);
}
}

The lines we are interested in are the calls to helper(...) on the classes WithoutStaticMethods and WithStaticMethods.

Without static methods

In the first case, without static methods, when you call the helper method the JVM needs to push the reference to the instance to pass it to invokespecial. Take a look at the code of the calculate() method:

 0 aload_0
1 aload_0
2 getfield #2 <app/WithoutStaticMethods.value>
5 iconst_2
6 aload_0
7 getfield #2 <app/WithoutStaticMethods.value>
10 imul
11 invokespecial #3 <app/WithoutStaticMethods.helper>
14 ireturn

The instruction at 0 (or 1), aload_0, will load the reference to the instance on the stack, and it will be consumed later by invokespecial. This instruction will put that value as the first parameter of the helper(...) function, and it is never used, as we can see here:

0 iload_1
1 iload_2
2 imul
3 iconst_1
4 iadd
5 ireturn

See there's no iload_0? It has been loaded unnecessarily.

With static methods

Now, if you declare the helper method, static, then the calculate() method will look like:

 0 aload_0
1 getfield #2 <app/WithStaticMethods.value>
4 iconst_2
5 aload_0
6 getfield #2 <app/WithStaticMethods.value>
9 imul
10 invokestatic #3 <app/WithStaticMethods.helper>
13 ireturn

The differences are:

  • there's one less aload_0 instruction
  • the helper method is now called with invokestatic

Well, the code of the helper function is also a little bit different: there's no this as the first parameter, so the parameters are actually at positions 0 and 1, as we can see here:

0 iload_0
1 iload_1
2 imul
3 iconst_1
4 iadd
5 ireturn

Conclusion

From the code design angle, it makes much more sense to declare the helper method static: the code speaks for itself, it contains more useful information. It states that it does not need instance state to work.

At the bytecode level, it is much more clear what is happening, and there's no useless code (that, although I believe the JIT has no way to optimize it, would not incur a significant performance cost).

Should class methods be made static in all cases if they don't use absolutely any class fields?

If a method doesn't use any instance variables in it's containing class then it doesn't have to be static, but it should be. As a general rule, if a method doesn't require a class instantiation to be used then it should be extracted to a utility class/interface as a static method.

Should I make my private class methods static?

If the methods don't access any of the type's state then they should be static.

Static method calls provide a performance gain over instance methods and the presence of a static method tells future readers of your code that calling this method will create no side effects in the the state of the current instance of the type.

The performance gain of a static method comes from the fact that the compiler does not have to emit callvirt instructions to call a static method. The callvirt instruction is handy for instance calls in that it does a null check prior to calling the method. However, when you call a static methods there is no need to check for null so the compiler is free to emit the faster call instruction which doesn't check for null.

Using private static methods

A private static method by itself does not violate OOP per se, but when you have a lot of these methods on a class that don't need (and cannot*) access instance fields, you are not programming in an OO way, because "object" implies state + operations on that state defined together. Why are you putting these methods on that class, if they don't need any state?

(*) = In principle, due to the class level visibility in Java, a static method on a class has access to instance fields of an object of that class, for example:

class Test
{
int field = 123;

private static void accessInstance(Test test)
{
System.out.println(test.field);
}
}

You need to pass in the reference to an instance (this pointer) yourself of course, but then you are essentially mimicking instance methods. Just mentioning this for completeness.



Related Topics



Leave a reply



Submit