2009-10-07 45 views
33

我已阅读下面的讨论:在什么情况下静态方法是一种好的做法?

Should private helper methods be static if they can be static,并且
Should all methods be static if their class has no member variables

看来,一般人会接受静态方法,但都有点怀疑它,有以下两个原因:

  1. 他们很难测试。
  2. 他们违反了OO原则。 (他们 是功能,而不是方法,说 人。)

而且最能接受的静态方法私有静态的。但是为什么静态方法完全存在,以及在什么情况下它们是被优先采用的首要任务?

+0

这个讨论也很有用:什么时候不在Java中使用static关键字http://stackoverflow.com/questions/1766715/when-not-to-use-the-static-keyword-in-java – 2013-02-12 13:33:23

回答

52

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

我认为静态方法很好,当他们是私人的,当他们是“实用”的方法 - 例如,做字符串转义。问题出现在你使用静态方法的时候,你希望能够模拟出或者在测试中替换掉。工厂方法也可以使用,尽管依赖注入通常是一种更好的方法 - 再次,它部分取决于您是否希望能够替换测试中的功能。至于不是“OO” - 并非所有用OO语言编写的所有内容都必须是“纯粹的”OO。有时非OO路线更加实用,并导致更简单的代码。 Eric Lippert在这方面有一篇很棒的博客文章,很不幸我现在找不到。但是,在this post中有相关的评论。它讨论的是扩展方法而不是静态方法,但原理是一样的。

扩展方法经常被批评 为“不OOP不够。”这似乎是 对我来说,把车放在马的前面 。 OOP的目的是为 由 队的人写的大型软件项目的结构 谁不需要 知道为了 生产各 其他工作的内部细节提供指引。 C#的目的是成为 这种有用的编程语言,它使我们的客户能够在我们的平台上高效地生产 。显然OOP是 有用和流行,并且我们已经 因此试图使在C#中的OOP风格的程序易于 。但是C#的目的不是“成为OOP 语言”。我们根据 评估功能是否对我们的 客户有用,而不是基于它们是否严格遵守一些抽象的 理论,这些理论是为了使面向对象的语言成为 。我们 高兴地从oo, 功能,程序,命令, 声明,只要我们 可以使一个有益的产品 有利于我们的客户。

+0

非常真实,允许更简洁的代码,并且更容易重用。 – 2009-10-07 08:55:42

+0

谢谢。很好的解释。所以你认为效用方法是一个好习惯,对吧?但后来我不明白为什么人们会使用静态,然后“私人”或“实用”。基本上,我使用实用方法很多。 – 2009-10-07 09:01:45

+2

嗯,它是任何时候你写一个逻辑上与该类型相关的方法而不是该类型的一个实例。在一些地区这很常见,在其他国家很少见。 – 2009-10-07 09:19:32

1

我觉得对于静态方法一定情况下是当你不能让他们动态的,因为你不能修改类

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

5

想一想这一刻。在面向对象的编码,每一个函数调用实际上是这样的:

method(object this, object arg1, object arg2)哪里这是您呼叫的对象。所有它真的是这样的语法糖。此外它可以让你清楚地定义的变量的作用域,因为你有对象变量等

静态方法根本就没有“这个”参数。即你传入变量并可能返回结果。 1.)是人们避免它们的主要原因,你不能创建静态方法的接口(还),所以你不能模拟出静态方法来测试它。

二OO是程序功能等静态方法作出了很大的意义在某些情况下,但他们总是可以做成一个对象的方法。

你要知道,你不能没有一个黑客删除此:

static void Main(string[] args) 
{ 
} 

启动您的应用程序必须调用但没有一个对象的引用代码。所以他们给你灵活性,无论你选择在你的场景中使用它们,都会根据你的要求来决定。

16

我会说静态方法肯定是好的,当他们是函数,即他们没有做任何IO,没有任何内部状态,只使用他们的参数来计算他们的返回值。

我还希望这个延伸到改变其参数的状态,但如果这种过度进行,静态方法应该是正确的,它主要经营的参数类的实例方法的方法。

2

静态方法的另一个很好的方案是在一个特定的方式来构建的Factory pattern,你在哪里,允许类的实例的实现。

考虑Calendar类,它具有一组静态getInstance方法,每种情况下返回与所需TimeZone和/或Locale或默认灌注。

+0

我没有使用依赖注入,也没有(经常)模拟对象进行测试,但实现工厂的静态方法会使嘲笑变得不可能,不是吗? – 2009-10-07 09:34:53

3

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

例如,以一个简单的工具,如提高原始的力量 - 很明显,你永远需要有任何的多态性。原始值是静态类型的,而数学运算是明确定义的,不会改变。这并不是说你永远不会得到两个differentimplementations无法在不重写所有客户端代码的情况下切换它们的情况。


(讽刺关闭)

现代JVM是在如果只有一个实现接口的加载内嵌小型调用不错。除非你对你的代码进行了简介,并且知道把你的工具分配给一个界面是一种开销,否则你没有理由不让你的utility methods into an interface如果需要可以改变。

1

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

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

该方法还提供了基于他们所做的事情命名“构造函数”的可能性。当参数本身不足以找出构造函数中发生的情况时,这是特别有用的。

太阳将使用

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

Boolean.valueOf("true"); 
1

首先的这种方法,你不能排除静态的方法是有原因的人还在使用它。

  1. 一些设计模式是基于静态方法中,单例如:

    Config.GetInstance();

  2. 辅助函数,可以说你有一个字节流,你想要一个函数将它转换成一串十六进制数字。

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

1

Util类可以是静态的。正如在上面的某个人中,使用转义字符串。问题在于,这些utils类执行我们想要模拟的功能。例如,apache commons中的FileUtils类 - 通常情况下,我想要模拟文件交互而不必使用真实文件。如果这是一个实例类,那很容易。

1

重构静态方法要容易得多。它不鼓励不必要地提到使接头紧密的现场成员。理解调用代码也更容易,因为它明确地传递了它所交互的任何对象。

0

通常我会在单个实例正常工作时避免使用静态方法。该单个实例可以实现一个接口,并且可以轻松地进行模拟。我不是说从不,但我很少使用静力学。我告诉我的团队,如果他们想要使用静态,应该由团队清理。我的答案几乎从不是。

相关问题