In Java, is there any disadvantage to static metho

2019-01-14 10:30发布

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?)

14条回答
Root(大扎)
2楼-- · 2019-01-14 11:15

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

查看更多
看我几分像从前
3楼-- · 2019-01-14 11:15

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...

查看更多
ゆ 、 Hurt°
4楼-- · 2019-01-14 11:20

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.

查看更多
▲ chillily
5楼-- · 2019-01-14 11:20

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.

查看更多
兄弟一词,经得起流年.
6楼-- · 2019-01-14 11:21

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.

查看更多
啃猪蹄的小仙女
7楼-- · 2019-01-14 11:23

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.

查看更多
登录 后发表回答