views:

925

answers:

13

Lets assume that a rule (or rule of thumb, anyway), has been imposed in my coding environment that any method on a class that doesn't use, modify, or otherwise need any instance variables to do its work, be made static. Is there any inherent compile time, runtime, or any other disadvantage to doing this?

(edited for further clarifications)

I know the question was somewhat open ended and vague so I apologize for that. My intent in asking was in the context of mostly "helper" methods. Utility classes (with private CTORs so they can't be instantiated) as holders for static methods we already do. My question here was more in line of these little methods that HELP OUT the main class API.

I might have 4 or 5 main API/instance methods on a class that do the real work, but in the course of doing so they share some common functionality that might only be working on the input parameters to the API method, and not internal state. THESE are the code sections I typically pull out into their own helper methods, and if they don't need to access the class' state, make them static.

My question was thus, is this inherently a bad idea, and if so, why? (Or why not?)

A: 

No, actually the reason for that advice is that it provides a performance advantage. Static methods can be called with less overhead so any method that doesn't need a reference to this ought to be made static.

Andrew Hare
Note the performance hit is extremely minor.
NateS
+14  A: 

The main disadvantage is that you cannot swap, override or choose method implementations at runtime.

cherouvim
+1 even if the method doesn't need any of the objects state, it could still depend on the objects type, but only if it's *not* `static`.
Joachim Sauer
+1; some folks say that `static` is NOT object-oriented concept (for the reasons you are talking about). And in Java there is almost 0 performance boost for static methods vs. member methods (look into compiled byte code -- it is a matter of pushing an object reference to stack -- must be several picoseconds or so :) Furthermore, if you use reflection with static methods, you still need to pass `null` as the first argument to `invoke()`.
incarnate
@Sauer Function objects are a good example for these
Helper Method
A: 

No there is no disadvantages, rather when you are not accessing any instance members in the method then there is no meaning of having it as an instance method. It is good programming skill to have it as a static method.

and adding to that you don't have to create any instances to access these methods and thus saving a memory and garbage collecting time.

GK
A: 

One disadvantage is if your static methods are general and distributed in different classes as far as usage is concerned. You might consider putting all static methods that are general in a utility class.

Joset
Not necessarily good advice. A method shouldn't be pulled out of a class by virtue of being static. Only if you have methods that do not fit in with your classes would you consider pulling them into "utility" classes. For example, if you intend to augment the language's String class or provide additional Collection methods. You *want* static methods in the classes they belong to.
Jonathon
edit: static methods that are general
Joset
+9  A: 

The performance advantage is likely negligible. Use static methods for anything that's not state dependent. This clarifies the code, as you can immediately see with a static method call that there's no instance state involved.

Steve B.
Not only that, but it makes unit testing *significantly* easier. And you are writing tests, right?
Callahad
Often it can make unit testing significantly harder, especially legacy code that was not written in a way that can be unit tested.
Yishai
@Yishai Could you clarify? If the method is static, its output is determined solely by its inputs, and not any external state. How can that constraint make unit testing more difficult?
Callahad
@Callahad, by having a static method cannot be mocked or abstracted. So if that static method calls a web service, hits a database, starts a thread or does anything similar that is not unit testable, it makes it much more difficult to mock, abstract or otherwise redirect the method to something else under test.
Yishai
@Callahad Ever tried to mock a singleton? Static method can not be replaced by dummy implementation easily (though it's possible with advanced mocking framework)
ewernli
Yishai, calling a web service or a database is not state-independant. In a DI framework those are dependencies injected into a singleton and are part of the singleton's state. I don't think those would be properly modeled with statics.
Steve B.
A: 

As others have said, it provides a slight performance advantage and is good programming practice. The only exception is when the method needs to be an instance method for overriding purposes, but those are usually easily recognised. For example if a class provides default behaviour of an instance method, that happens not to need instance variables, that clearly can't be made static.

DJClayworth
As others have said, there is no performance advantage for static methods (at least in Java).
incarnate
+2  A: 

In order to call the static methods you don't need to create class objects. The method is available immediately.

Assuming the class is already loaded. Otherwise there's a bit of a wait. :-)

I think of static as a good way to separate the functional code from procedural/state-setting code. The functional code typically needs no extension and changes only when there are bugs.

There's also the use of static as an access-control mechanism--such as with singletons.

HonorGod
A: 

I really like this question as this has been a point I have been debating for last 4 years in my professional life. Static method make a lot of sense for classes which are not carrying any state. But lately I have been revised my though somewhat.

Utility classes having static methods is a good idea.

Service classes carrying business logic can be stateless in many cases. Initially I always added static methods in them, but then when I gained more familiarity with Spring framework (and some more general reading), I realized these methods become untestable as an independent unit as u cannot inject mock services easily into this class. E.g. A static method calling another static method in another class, there is no way JUnit test can short circuit tis path by injecting a dummy implementation at run time.

So I kind of settled to the thought that having utility static methods which do not need to call other classes or methods pretty much can be static. But service classes in general should be non static. This allows you to leverage OOPs features like overriding.

Also having a singleton instance class helps us to make a class pretty much like a static class still use OOPs concepts.

Fazal
Since overriding should only be done to methods that were designed with the intent of being overridden, I don't see this as a driving reason to make all possible methods non-static. Personally, the difference is negligible, especially for private code, so a better reason is just less typing. :)
NateS
A: 

In general:

You should be writing your software to take advantage of interfaces and not implementations. Who's to say that "now" you won't use some instance variable, but in the future you will? An example of coding to interfaces...

ArrayList badList = new ArrayList();  //bad
List goodList = new ArrayList();  //good

You should be allowed to swap implementations, especially for mocking & testing. Spring dependency injection is pretty nice in this respect. Just inject the implementation from Spring and bingo you have pretty much a "static" (well, singleton) method...

Now, those types of APIs that are purely "utility" in purpose (i.e., Apache Commons Lang) are the exception here because I believe that most (if not all) of the implementations are static. In this situation, what are the odds that you will want to ever swap Apache Commons out for another API?

Specifically:

How would you elegantly handle the "staticness" of your implementation when you're targeting, say, a Websphere vs. Tomcat deployment? I'm sure there would be an instance (no pun intended) of when your implementation would differ between the two...and relying on a static method in one of those specific implementations might be dangerous...

T Reddy
There is a cost in efficiency to this. You might want to publish only generic interfaces, but for internal code, hardcoding is faster, and all it takes to switch is editing the references to the type. The reason you publish interfaces is that you cannot go and fix all the references external to your code.
Dov
I'm not seeing how this is related to the question? Also, there is nothing wrong with using concrete types in private code. Only in a public API is it good coding practice.
NateS
@NateS I believe my answer is completely related to the question. We have a framework API that we must port over from Websphere to Tomcat. The "private code" is littered with references to Websphere-specific "stuff". Life would've been much easier had this code simply used some interface that was a proxy to the Websphere implementation.
T Reddy
Interfaces aren't proxies, they are Types that define a Contract that implemenations must adhere to. An Interface can't "do" anything on behalf of anyone. Thus it fails the definition of proxy.
fuzzy lollipop
@Dov never code for efficiency, always code for maintainability. If you find your code does not meet defined specs, start trying to profile and make changes if you must. Anyone finding themselves worrying about efficiency ahead of maintainability should recognize it as an indication of a problem.
Bill K
There is a big difference between optimizing your code, and knowing how to write efficient code. If you focus only on maintainability, and don't know or care about the efficiency of your code, then your code can be uniformly slow.If you know what you're doing, efficiency of your low-level code is effortlessly good. Example: for a list, a programmer who doesn't understand will use a linked list and keep referring to the ith member. Better, use an iterator. Someone who understands the costs would use an ArrayList with preallocated space. It's no less maintainable, and it's a lot faster.
Dov
A: 

It's all a question of context. Some people have already given examples where static is absolutely preferable, such as when writing utility functions with no conceivable state. For example, if you are writing a collection of different sort algorithms to be used on arrays, making your method anything but static just confuses the situation. Any programmer reading your code would have to ask, why did you NOT make it static, and would have to look to see if you are doing something stateful to the object.

public class Sorting {
  public static void quiksort(int [] array) {}
  public static void heapsort(int[] array) { }
}

Having said that, there are many people who write code of some kind, and insist that they have some special one-off code, only to find later that it isn't so. For example, you want to calculate statistics on a variable. So you write:

public class Stats {
  public static void printStats(float[] data) { }
}

The first element of bad design here is that the programmer intends to just print out the results, rather than generically use them. Embedding I/O in computation is terrible for reuse. However, the next problem is that this general purpose routine should be computing max, min, mean, variance, etc. and storing it somewhere. Where? In the state of an object. If it were really a one-off, you could make it static, but of course, you are going to find that you want to compute the mean of two different things, and then it's awfully nice if you can just instantiate the object multiple times.

public class Stats {
  private double min,max,mean,var;
  public void compute(float data[]) { ... }
  public double getMin() { return min; }
  public double
}

The knee jerk reaction against static is often the reaction of programmers to the stupidity of doing this sort of thing statically, since it's easier to just say never do that than actually explain which cases are ok, and which are stupid.

Note that in this case, I am actually using the object as a kind of special-purpose pass by reference, because Java is so obnoxious in that regard. In C++, this sort of thing could have been a function, with whatever state passed as references. But even in C++, the same rules apply, it's just that Java forces us to use objects more because of the lack of pass by reference.

As far as performance goes, the biggest performance increase of switching from a regular method is actually avoiding the dynamic polymorphic check which is the default in java, and which in C++ is specified manually with virtual.

When I tried last there was a 3:1 advantage of calling a final method over a regular method, but no discernible for calling static functions over final.

Note that if you call one method from another, the JIT is often smart enough to inline the code, in which case there is no call at all, which is why making any statement about exactly how much you save is extremely dangerous. All you can say is that when the compiler has to call a function, it can't hurt if it can call one like static or final which requires less computation.

Dov
A: 

In my opinion, there are four reasons to avoid static methods in Java. This is not to say that static methods are never applicable, only to say that they should generally be avoided.

  1. As others have pointed out, static methods cannot be mocked out in a unit test. If a class is depending on, say, DatabaseUtils.createConnection(), then that dependent class, and any classes that depend on it, will be almost impossible to test without actually having a database or some sort of "testing" flag in DatabaseUtils. In the latter case, it sounds like you actually have two implementations of a DatabaseConnectionProvider interface -- see the next point.

  2. If you have a static method, its behavior applies to all classes, everywhere. The only way to alter its behavior conditionally is to pass in a flag as a parameter to the method or set a static flag somewhere. The problem with the first approach is that it changes the signature for every caller, and quickly becomes cumbersome as more and more flags are added. The problem with the second approach is that you end up with code like this all over the place:

 boolean oldFlag = MyUtils.getFlag();
 MyUtils.someMethod();
 MyUtils.setFlag( oldFlag );
 

One example of a common library that has run into this problem is Apache Commons Lang: see StringUtilsBean and so forth.

  1. Objects are loaded once per ClassLoader, which means that you could actually have multiple copies of your static methods and static variables around unwittingly, which can cause problems. This usually doesn't matter as much with instance methods, because the objects are ephemeral.

  2. If you have static methods that reference static variables, those stay around for the life of the classloader and never get garbage collected. If these accumulate information (e.g. caches) and you are not careful, you can run into "memory leaks" in your application. If you use instance methods instead, the objects tend to be shorter-lived and so are garbage-collected after a while. Of course, you can still get into memory leaks with instance methods too! But it's less of a problem.

Hope that helps!

Eric Galluzzo
+1  A: 

The main problem you may face is, you won't be able to provide a new implementation if needed.

If you still have doubts ( whether your implementation may change in the future or not ) you can always use a private instance underneath with the actual implementation:

 class StringUtil {
     private static StringUtil impl = new DefaultStringUtil();

     public static String nullOrValue( String s ) {
          return impl.doNullOrValue();
     }
     ... rest omitted 
  }

If for "some" reason, you need to change the implementation class you may offer:

  class StringUtil {
     private static StringUtil impl = new ExoticStringUtil();

     public static String nullOrValue( String s ) {
          return impl.doNullOrValue(s);
     }
     ... rest omitted 
  }

But may be excessive in some circumstances.

OscarRyz
A: 

There shouldn't be any disadvantages--there may even be a slight advantage in performance (although it wouldn't be measurable) since the dynamic lookup can be avoided.

It's nice to tag functions as functions instead of having them look like Methods--(and static "Methods" ARE functions, not methods--that's actually by definition).

In general a static method is a bad OO code smell--it probably means that your OO model isn't fully integrated. This happens all the time with libraries that can't know about the code that will be using it, but in integrated non-library code static methods should be examined to evaluate which of it's parameters it's most closely associated with--there is a good chance it should be a member of that class.

If a static method just takes native values, then you're probably missing a handful of classes; you should also keep passing native variables or library objects (like collections) to a minimum--instead containing them in classes with business logic.

I guess what I'm saying is that if this is really an issue, you might want to re-examine your modeling practices--statics should be so rare that this isn't even an issue.

Bill K
-1 I don't like what you said?
Bill K