在Java中,类上的静态方法有什么缺点吗?

2022-09-01 03:29:11

让我们假设在我的编码环境中强加了一条规则(或经验法则),即类上不使用,修改或以其他方式不需要任何实例变量来完成其工作的任何方法都应设置为静态。这样做是否有任何固有的编译时间,运行时或任何其他缺点?

(已编辑以作进一步澄清)

我知道这个问题有些开放和模糊,所以我对此表示歉意。我问这个问题的意图主要是在“帮助者”方法的背景下。实用程序类(带有私有 CTOR,因此它们无法实例化)作为我们已经执行的静态方法的持有者。我在这里的问题更符合这些小方法,这些方法有助于主类API。

我可能在一个类上有4或5个主要的API /实例方法,这些方法可以完成真正的工作,但是在此过程中,它们共享一些通用功能,这些功能可能只处理API方法的输入参数,而不是内部状态。这些是我通常提取到它们自己的帮助器方法中的代码部分,如果它们不需要访问类的状态,请使它们成为静态的。

因此,我的问题是,这本质上是一个坏主意吗?如果是,为什么?(或者为什么不呢?


答案 1

在我看来,在Java中避免静态方法有四个原因。这并不是说静态方法从不适用,只是说通常应该避免使用它们。

  1. 正如其他人所指出的,静态方法不能在单元测试中被嘲笑出来。如果一个类依赖于 ,比如说,那么该依赖类以及依赖于它的任何类,如果没有实际具有数据库或中的某种“测试”标志,几乎不可能进行测试。在后一种情况下,听起来你实际上有两个接口的实现 - 请参阅下一点。DatabaseUtils.createConnection()DatabaseUtilsDatabaseConnectionProvider

  2. 如果您有一个静态方法,则其行为适用于所有位置的所有类。有条件地更改其行为的唯一方法是将标志作为参数传递给方法,或在某处设置静态标志。第一种方法的问题在于,它会更改每个调用方的签名,并且随着添加越来越多的标志而很快变得繁琐。第二种方法的问题在于,你最终会到处都是这样的代码:

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

    遇到这个问题的通用库的一个例子是Apache Commons Lang:参见StringUtilsBean等等。

  3. 每个 ClassLoader 的对象加载一次,这意味着您实际上可能会在不知不觉中拥有静态方法和静态变量的多个副本,这可能会导致问题。这通常与实例方法无关紧要,因为对象是短暂的。

  4. 如果您有引用静态变量的静态方法,这些方法在类装入器的生命周期中一直存在,并且永远不会被垃圾回收。如果这些信息累积了(例如缓存),而您不小心,则可能会在应用程序中遇到“内存泄漏”。如果改用实例方法,则对象的生存期往往较短,因此会在一段时间后被垃圾回收。当然,您仍然可以使用实例方法进行内存泄漏!但这不是一个问题。

希望有所帮助!


答案 2

主要缺点是您无法在运行时交换,重写或选择方法实现。


推荐