关于java:在什么情况下静态方法是一个好习惯?

In what situations is static method a good practice?

我已阅读以下讨论:

如果私有helper方法可以是静态的,那么它们应该是静态的,并且如果它们的类没有成员变量,那么所有方法都应该是静态的吗

一般来说,人们似乎会接受静态方法,但对此有点怀疑,原因如下2:

  • 它们很难测试。
  • 它们违反了OO原则。(他们是函数,而不是方法个人。)
  • 最可接受的静态方法是私有静态方法。但是,为什么静态方法存在呢?在什么情况下,静态方法是首选的呢?


    静态方法本身并不难测试。问题是调用静态方法的其他代码很难测试,因为您不能替换静态方法。

    我认为静态方法在私有或"实用"方法(例如字符串转义)时都可以。当您对想要在测试中模拟或替换的东西使用静态方法时,问题就出现了。工厂方法也很有用,尽管依赖注入通常是一种更好的方法——同样,它部分取决于您是否希望能够替换测试中的功能。

    至于不是"oo"——不是你用一般的oo语言写的所有东西都必须是"纯"的oo。有时,非OO路由只是更实用,导致代码更简单。埃里克·利珀特写了一篇很好的博客,可惜我现在找不到。然而,这篇文章中有一个相关的评论。它讨论的是扩展方法而不是静态方法,但原理是相同的。

    Extension methods are often criticized
    as being"not OOP enough". This seems
    to me to be putting the cart in front
    of the horse. The purpose of OOP is to
    provide guidelines for the structuring
    of large software projects written by
    teams of people who do not need to
    know the internal details of each
    other's work in order to be
    productive. The purpose of C# is to be
    a useful programming language that
    enables our customers to be productive
    on our platforms. Clearly OOP is both
    useful and popular, and we've
    therefore tried to make it easy to
    program in an OOP style in C#. But the
    purpose of C# is not"to be an OOP
    language". We evaluate features based
    on whether they are useful to our
    customers, not based on whether they
    conform strictly to some abstract
    academic ideal of what makes a
    language object-oriented. We'll
    happily take ideas from oo,
    functional, procedural, imperative,
    declarative, whatever, so long as we
    can make a consistent, useful product
    that benefits our customers.


    我要说的是,静态方法在作为函数时是绝对正常的,即它们不做任何IO,没有任何内部状态,只使用它们的参数来计算它们的返回值。

    我还将把它扩展到更改参数状态的方法,尽管如果做得太多,静态方法应该是它主要操作的参数类的一个实例方法。


    想想这个。在OO编码中,每个函数调用实际上如下所示:

    method(object this, object arg1, object arg2),这里是您要调用的对象。它真正的意义是语法糖。此外,它允许您清楚地定义变量的范围,因为您有对象变量等。

    静态方法没有"this"参数。也就是说,你输入变量,可能会得到一个结果。1.)是人们回避它们的主要原因,您还不能创建一个静态方法的接口,所以您不能模拟出静态方法来测试它。

    其次,OO是程序函数等,静态方法在某些情况下有很大的意义,但它们总是可以在一个对象上形成一个方法。

    注意,如果没有黑客,你就无法删除:

    1
    2
    3
    static void Main(string[] args)
    {
    }

    启动应用程序的代码必须可以在不引用对象的情况下调用。因此,它们给了您灵活性,您是否选择在您的场景中使用它们将由您的需求来预测。


    静态方法在大多数情况下都很好,因为单例模式提供了太多的灵活性。

    例如,以一个简单的实用程序为例,比如将一个原语提升到一个能力——显然,您不需要在这方面有任何多态性。原始值是静态类型的,数学运算定义良好且不会改变。如果不重写所有客户机代码,就不会有两种不同的实现在它们之间切换的情况。

    (讽刺的是)

    如果只加载一个接口的一个实现,那么现代JVM非常擅长于嵌入小调用。除非您已经对代码进行了分析,并且知道将实用程序分派到一个接口是一项开销,否则您没有理由不将实用程序方法制作成一个可以根据需要进行更改的接口。


    静态方法的另一个好方案是工厂模式的实现,在工厂模式中允许以特定的方式构造类的实例。

    考虑Calendar类,它有一组静态的getInstance方法,每个返回的实例都用所需的TimeZone和/或Locale或默认值启动。


    重构静态方法要容易得多。它不鼓励对使耦合紧密的字段成员进行不必要的引用。更容易理解调用代码,因为它显式地传递与之交互的任何对象。


    Util类可以是静态的。就像上面的其他人的例子一样,使用转义字符串。问题在于,当这些实用程序类执行我们想要模拟的函数时。例如,ApacheCommons中的fileutils类——通常情况下,我希望模拟文件交互,而不必使用真正的文件。如果这是一个实例类,就很容易了。


    首先,您不能忽略静态方法,人们仍然使用它是有原因的。

  • 有些设计模式基于静态方法,例如singleton:

    config.getInstance();

  • helper函数,假设您有一个字节流,并且希望函数将其转换为十六进制数的字符串。

  • 静态方法有很多用途,这并不意味着有些人滥用它太多(当人们滥用代码时,代码审查是最好的选择)。


    我经常使用静态工厂方法代替或与公共构造函数结合使用。

    我这样做,当我需要一个构造函数来做一些您不会期望构造函数做的事情时。即从文件或数据库加载设置。

    这种方法还提供了根据"构造器"的工作命名"构造器"的可能性。当参数本身不足以计算出构造函数中会发生什么时,这尤其有用。

    Sun在

    1
    Class.forName("java.lang.Integer");

    1
    Boolean.valueOf("true");


    我认为静态方法的一个明确情况是当您不能使它们成为动态的,因为您不能修改类。

    这对于JDK对象,以及来自外部库的所有对象,以及原始类型都是典型的。


    通常,当单个实例可以正常工作时,我会避免使用静态方法。这个单一的实例可以实现一个接口,并且可以很容易地被模拟。我不是说从不,但我很少用静力学。我告诉我的团队,如果他们想使用静电,应该由团队清除。几乎从来都不是我的答案。