在 Java 中,类上的静态方法有什么缺点吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2472690/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
In Java, is there any disadvantage to static methods on a class?
提问by Michael Campbell
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.
我知道这个问题有点开放和模糊,所以我为此道歉。我询问的意图主要是在“助手”方法的背景下。实用程序类(带有私有 CTOR,因此它们不能被实例化)作为我们已经做的静态方法的持有者。我在这里的问题更符合这些帮助主类 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.
我可能在一个类上有 4 或 5 个主要的 API/实例方法来完成真正的工作,但在这样做的过程中,它们共享一些可能仅适用于 API 方法的输入参数而不适用于内部状态的通用功能. 这些是我通常提取到它们自己的辅助方法中的代码部分,如果它们不需要访问类的状态,请将它们设为静态。
My question was thus, is this inherently a bad idea, and if so, why? (Or why not?)
因此,我的问题是,这本质上是一个坏主意,如果是,为什么?(或者为什么不呢?)
采纳答案by cherouvim
The main disadvantage is that you cannot swap, override or choose method implementations at runtime.
主要缺点是您不能在运行时交换、覆盖或选择方法实现。
回答by Andrew Hare
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.
不,实际上,该建议的原因是它提供了性能优势。可以以较少的开销调用静态方法,因此任何不需要引用的方法都this
应该是静态的。
回答by GuruKulki
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.
此外,您不必创建任何实例来访问这些方法,从而节省内存和垃圾收集时间。
回答by setzamora
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.
一个缺点是,就使用而言,您的静态方法是通用的并且分布在不同的类中。您可能会考虑将所有通用的静态方法放在一个实用程序类中。
回答by Steve B.
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.
性能优势可能可以忽略不计。对任何不依赖于状态的事物使用静态方法。这澄清了代码,正如您可以通过静态方法调用立即看到不涉及实例状态。
回答by DJClayworth
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.
正如其他人所说,它提供了轻微的性能优势,是很好的编程实践。唯一的例外是当该方法需要是用于覆盖目的的实例方法时,但这些通常很容易识别。例如,如果一个类提供了一个实例方法的默认行为,那恰好不需要实例变量,这显然不能成为静态的。
回答by jagamot
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.
还有使用静态作为访问控制机制——例如单例。
回答by Fazal
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.
我真的很喜欢这个问题,因为这是我过去 4 年职业生涯中一直在争论的一个问题。静态方法对于不携带任何状态的类很有意义。但最近我已经修改了我的虽然有点。
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.
在许多情况下,承载业务逻辑的服务类可以是无状态的。最初我总是在它们中添加静态方法,但是当我对 Spring 框架更加熟悉(以及一些更一般的阅读)时,我意识到这些方法作为一个独立的单元变得不可测试,因为你不能轻易地将模拟服务注入到这个类中。例如,一个静态方法调用另一个类中的另一个静态方法,JUnit 测试无法通过在运行时注入虚拟实现来短路该路径。
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.
所以我有点接受这样的想法,即具有几乎不需要调用其他类或方法的实用程序静态方法可以是静态的。但是服务类一般应该是非静态的。这允许您利用 OOP 功能,例如覆盖。
Also having a singleton instance class helps us to make a class pretty much like a static class still use OOPs concepts.
还有一个单例实例类可以帮助我们创建一个非常像静态类的类,仍然使用 OOPs 概念。
回答by Tim Reddy
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...
您应该被允许交换实现,尤其是对于模拟和测试。Spring 依赖注入在这方面非常好。只需从 Spring 和宾果游戏中注入实现,你就有了一个“静态”(好吧,单例)方法......
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?
现在,那些纯粹出于“实用”目的的 API(即 Apache Commons Lang)在这里是个例外,因为我相信大多数(如果不是全部)实现都是静态的。在这种情况下,您希望将 Apache Commons 换成另一个 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...
当您的目标是 Websphere 与 Tomcat 部署时,您将如何优雅地处理实现的“静态性”?我确信会有一个实例(没有双关语)你的实现在两者之间会有所不同......并且在这些特定实现之一中依赖静态方法可能是危险的......
回答by Dov
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.
这里糟糕设计的第一个元素是程序员打算只打印结果,而不是一般地使用它们。在计算中嵌入 I/O 对于重用来说很糟糕。然而,下一个问题是这个通用例程应该计算最大值、最小值、均值、方差等并将其存储在某个地方。在哪里?处于对象状态。如果它真的是一次性的,你可以让它成为静态的,但是当然,你会发现你想要计算两个不同事物的平均值,然后如果你可以多次实例化对象,那就太棒了.
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.
请注意,在这种情况下,我实际上将对象用作一种特殊用途的引用传递,因为 Java 在这方面非常令人讨厌。在 C++ 中,这种东西可能是一个函数,任何状态作为引用传递。但即使在 C++ 中,同样的规则也适用,只是 Java 由于缺少引用传递而迫使我们更多地使用对象。
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.
就性能而言,从常规方法切换的最大性能提升实际上是避免了动态多态检查,这在java中是默认的,而在C++中则是用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.
当我最后一次尝试时,调用 final 方法比调用常规方法有 3:1 的优势,但调用静态函数比调用 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.
请注意,如果您从另一个方法调用一个方法,JIT 通常足够智能以内联代码,在这种情况下根本没有调用,这就是为什么对您节省的确切数量进行任何声明是极其危险的。你只能说,当编译器必须调用一个函数时,如果它可以调用像 static 或 final 这样需要较少计算的函数,它不会有什么坏处。