如果它们的类没有成员变量,那么所有方法都应该是静态的

时间:2009-03-18 14:12:47

标签: java static

我刚与我合作过的人发生过争吵,这真的让我烦恼。如果你有一个只有calculateRisk或/和calculatePrice等方法的类,那么该类是不可变的并且没有成员变量,如果这些方法是静态的,那么就不必创建一个实例。每次上课。我使用以下示例:

public class CalcService {
  public int calcPrice(Trade trade, Date date) {
    ...
  }
  public double calcRisk(Trade trace, Date date) {
    ...
  }
}

这些方法应该是static吗?

20 个答案:

答案 0 :(得分:36)

您描述的类只是一组仅对输入进行操作的函数。将这些函数作为类的静态方法是完全合理的。这样做会对它们进行逻辑分组并消除可能的名称冲突。该类实际上充当命名空间,仅此而已。

答案 1 :(得分:23)

我会说是的,但在这种情况下也可以将这些方法放在Trade对象上。

答案 2 :(得分:19)

出于可测试性的原因,现在人们普遍反对静态类。

这是因为静态类无法实现接口,因此如果需要,不能轻易替换测试类。我认为像这样处理价格的案例就是一个很好的例子。未来有可能有多种计算价格的方法,并且能够在需要时将这些计算器替换为彼此。

现在可能没用,但我发现不使用静态类比使用静态类更有优势。

答案 3 :(得分:7)

这是一个艰难的决定。记住Josh Bloch says about APIs

  像钻石一样的API是   永远。你有一次机会得到它   好吧,给你最好的。

(这可能不是公共API,但如果您有同事要使用此代码,它实际上是一个API。)如果您将这些方法声明为静态,则会限制其未来发展,并将状态合并到上课很难或不可能。您将不得不使用这些静态方法签名。如果您因为需要状态而决定让它们成为非静态的,那么您将打破客户端代码。我会说,如果有疑问,不要让它们变得静止。也就是说,静态实用程序类有一个包含一堆函数的地方(例如,计算圆的面积。)您的类可能属于该类。

答案 4 :(得分:7)

我会避免使这些静态。虽然目前可能有意义,但您可能在将来想要添加一些行为。例如目前您将拥有默认计算引擎(策略):

CalcService cs = new CalcService();
cs.calcPrice(trade, date);

以后你可能想要添加一个新的计算引擎:

CalcService cs = new CalcService(new WackyCalculationStrategy());
cs.calcPrice(trade, date);

如果你使这个类可以实例化,那么你可以创建不同的实例并传递它们,动态实例化等。你可以给它们长时间运行的行为(例如,有多少涉及交易X的计算完成了这个对象?等等)

答案 5 :(得分:4)

我会让整个事情变得静止。

答案 6 :(得分:4)

虽然您可以使用JMockit或任何类似工具来模拟静态方法,但我个人的选择是尽可能避免静态,因为静态方法通常会增加耦合。

有些答案暗示该方法是无状态的,但我真的不希望这样看。该方法以方法参数的形式接受状态。如果那些参数是在对象中的状态而该怎么办?

答案 7 :(得分:3)

答案是肯定的,不是。这一切都取决于方法行为的目的。例如:

  1. 如果这些方法只是实用方法,那么将它们设为静态是非常有意义的。

  2. 如果这些方法代表了应用程序的某种业务逻辑(比方说......一个Web应用程序),那么您可能希望尽可能灵活地使用它们。在这种情况下,它们将成为一个简单的POJO类,作为实例方法。这有一个不那么明显的好处,它们可以很轻松地转换为Spring事务bean,甚至是EJB3会话bean。它还使这些方法更容易测试。您还可以为此bean创建接口,并以您需要的方式添加其他方面。

答案 8 :(得分:3)

我显然会说

如果你调用静态方法而不是实例方法,将来更难更改。使用实例方法,可以轻松注入您的服务,例如:在Java中使用IoC / DI容器,如 Guice Spring

答案 9 :(得分:2)

Imo,他们应该是静态的。我认为没有理由不应该这样,因为实例对象没有状态,并且在没有实例化的情况下调用方法需要更少的代码,从而提高了可读性。

实际上,我可能会确保通过将它抽象化来实例化该类。

答案 10 :(得分:2)

我认为无状态方法通常应该是静态的。

  • 在代码中很明显没有对象 参与
  • 它避免了无意义的构造函数 调用

我可以看到违反这条规则的战略模式实施,正如许多人在此注意到的那样。

答案 11 :(得分:2)

如果将其设为静态,则无法轻松注入其他实现。

调用非静态方法不再需要任何运行时成本,因此对于新代码来说,尽可能避免静态。

OTOH,重构工具可以相当容易地替换对静态方法的所有调用,因此这种方式并不重要。

我不知道您的域名中的价格或风险的计算是否会有所不同。如果存在不同的策略,那么通过无状态策略实施可能会带来好处。但它的代码更多,并且YAGNI很有可能。

答案 12 :(得分:1)

这取决于你的目标:

如果你的目标是编写尽可能少的代码行,静态方法将是最好的。

如果您的目标是可测试性,我们发现静态方法是模拟出来的错误。遗憾的是,我们最终编写了一个界面,其中一些类只是为了能够轻松地模拟它们。

答案 13 :(得分:1)

如果方法需要在Trade实例中的信息来完成他们的工作,那么为什么这些方法不是Trade类的非静态成员?

答案 14 :(得分:1)

如果不明确要求将其设为“静态”,我建议您将它们设为实例。

不仅因为这会产生一种健康的做法,而且,如果你在将来可能会改变的生产代码中使用它,可能有一天你真的需要改变特定模块的实现并且不要因为这个原因,我不想打破整个应用程序。

同样,您的特定代码可能不会发生这种情况,但我曾经在这个应用程序中有大量类似这样的类(40 - 60或更多)

很多时候,将这些课程作为静力学,可以防止我们轻易改变某些模块并导致许多痛苦和眼泪。

如果我可以为这些特定部分注入新的实现,那将会更容易。

这个应用程序的代码行在500k而不是全部都在java中,这使得重构更难。

如果你在1k线项目中使用它,那么它根本不重要。

答案 15 :(得分:1)

在上面的答案中,我读到了由于测试原因而没有使其静止的论点。 我不明白为什么,但我不喜欢你正在使用的测试程序。

在我们公司,我们使用Junit进行单元和系统测试。 (org.junit) 使用此测试包测试静态方法完全没有问题。

所以我想说:是的,让它们静止。

(注意我不知道测试静态方法的测试程序是个问题)

答案 16 :(得分:1)

我最近遇到了同样的问题。我是usnig静态方法。此方法基本上返回保存所有用户定义设置所需的文件夹路径。现在的问题是我需要编写一个测试用例,它基本上可以清除文件夹中的所有内容。我绝对不想删除实际文件,因此我希望该方法返回其他内容。 Yakes ....我不能casue我不能模拟方法,因为它是静态的。留下没有运气但是将其更改为非静态方法并让类使用该方法实现接口。然后我可以轻松地模拟该接口并让该方法返回我想要的任何路径。

End result. Making it a not static gives you more functionality. Make class Singleton and you have everything a static does for you plus loosely coupling.

答案 17 :(得分:0)

在这种情况下,我可能会制作一些静态方法。我假设calc函数不依赖于其他资源来计算值,并且它通常与代码的其余部分隔离。

但是,一般来说,我倾向于回避在静态方法中做过于复杂的事情。如果你是单元测试并希望交换MockCalcService,那么在你的代码中散布静态调用将会非常困难。

答案 18 :(得分:0)

在我看来,它们应该是静态的。您甚至可能会获得性能改进,因为编译器/ jit可能会内联方法

答案 19 :(得分:0)

静止气味

在大多数情况下,静态方法是与数据分离的行为的示例。它表示某些内容未被封装。例如如果您在util类中看到电话号码,电子邮件等的验证方法,请问为什么它们不是这些字段没有自己的类。甚至库类也可以扩展以适应自定义行为。最后在特殊情况下,例如java.lang.String(最终的)你可以使用委托给java.lang.String的自定义myproject.String(带有附加行为)

对象是访问OO语言行为的方式。担心对象实例化的代价并使用静态代码是没有用的。对于大多数商业软件来说,这是一种“一分钱愚蠢”的表现方式。

有时,您使用仿函数(不使用对象状态的方法)来表达意图。并不意味着它们应该是静态的。建议“方法可以静态化”的IDE警告不应该被认真对待。