为什么不应该在所有私有方法中使用静态方法?

7

我正在尝试理解静态方法,但遇到了困惑的点。

仅关注方法,如果我创建一个对象实例(类本身不是静态的),那么通常只能访问公共、受保护或内部方法(取决于作用域/封装)。换句话说,我无法访问私有方法。

我读过静态方法比非静态方法略微更有效率的文章。

那么,当创建一个返回类型为void的私有方法时,除非在对象内部创建对象的引用,否则为什么不将其设置为静态?所有我见过的代码都没有这样做,所以我只能认为我错过了重点。


3
为了获得面向对象编程(OOP)的好处,你不应该将所有内容都设为“静态”,这与你需要实例相矛盾。因此,你需要使用实例。即使私有方法通常也与实例相关联。 - Tim Schmelter
7个回答

30

静态方法不能访问类中的非静态成员数据。


6

静态方法通常被认为是无状态的,因此无法访问实例状态。相比之下,实例方法是有状态的,因此可以读取和修改实例的状态。

无状态方法的典型示例包括:

  • 工厂方法
  • 二元操作符
  • ...

当然,静态方法并不总是无状态的,也有静态有状态方法的样例。这时候类仅有一个单一状态:

  • 单例
  • 实例池
  • ...

这些实现需要更多的注意,因为类的状态也会被进程中的所有线程共享。


1
我读到过这样的说法,即使很小,静态方法比非静态方法稍微更有效率。
但这并不是绝对正确的:只有那些本来可以是“静态”的方法,但因为遗漏而没有被定义为“静态”的方法才会更有效率。否则,你需要手动传递对象的引用,以平衡局面。此外,CLR已经被优化得如此之好,以至于很难测量出差异。
回答你的问题,如果一个方法不通过属性或变量访问实例状态,那么就没有理由将其定义为非静态方法。然而,所有访问每个实例状态的方法都应该是非静态的,以提高可读性,因为没有从使它们成为静态方法并手动传递实例中获得性能的好处。
为了说明这一点,你应该这样做:
private void AddCount(int number) {
    current += number;
}

不是这样的:

// Do not do this!
private static void AddCount(MyClass obj, int number) {
    obj.current += value;
}

1
如果这样做,您将无法访问类中的非静态成员。您可以将任何实例变量作为参数传递给私有静态函数,但特别是当函数与大量实例数据交互时,这可能会导致一些非常臃肿和难以阅读的代码。如果您正在操作类的实例成员,并且这不是可以在没有类实例的情况下完成的操作,则不应将其设为静态。

基本通则是,除非对类的所有实例都至关重要,否则不要使变量或函数静态化。当然也有例外情况,但如果您仅出于没有原因而使所有私有方法静态化,那么您很可能会违反面向对象编程范例。


0

我能想到两个原因:

  1. 你无法访问类中的其他非静态成员(如上所述)
  2. 你无法在子类中重写静态方法

在我看来,静态方法应该更多地作为一种例外。如果你想要在依赖注入容器中轻松访问应用程序的功能,最好使用单例 bean 并注入它,因为如果你需要的话,仍然可以轻松切换实现。

.NET 有一个特定的用例,即静态方法 - 扩展方法。因此,如果你想将你的功能作为扩展方法可用,就必须使用静态方法。


0

在代码中看到的大多数方法都会以某种方式使用非静态的类变量/属性。这些无法从静态上下文中访问。这意味着在静态方法中,您只能访问此类的静态成员而不是特定于对象的成员。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接