7

我试图理解静态方法,但我已经达到了一个令人困惑的地步。

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

我已经读过,虽然很少,但静态方法比非静态方法更有效。

因此,当创建一个返回类型为 void 的私有方法时,并且不包括从自身内部创建对象的引用时,为什么不将其设为静态呢?我见过的所有代码都没有这样做,所以我只能假设我错过了重点。

4

7 回答 7

29

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

于 2013-05-14T13:41:52.563 回答
6

静态方法通常应该是无状态的,因此无法访问实例状态。相反,实例方法是有状态的,因此可以读取和修改实例的状态。

无状态方法的典型例子有:

  • 工厂方法
  • 二元运算符
  • ...

当然,静态方法并不总是无状态的,有静态方法的示例。那么这个类只有一个状态

  • 辛格尔顿
  • 实例池
  • ...

不过,这些实现需要稍微多加注意,因为类的状态也由进程中的所有线程共享。

于 2013-05-14T13:42:54.867 回答
1

我已经读过,虽然很少,但静态方法比非静态方法更有效。

这不是无条件正确的:只有那些本来可以static但不是static遗漏的方法才会更有效率。否则,您将需要手动传递对对象的引用,从而提升游戏环境。此外,CLR 进行了如此多的优化,以至于很难衡量差异。

要回答您的问题,如果方法不通过属性或变量访问实例状态,则没有理由使方法成为非静态方法。但是,为了可读性,所有访问每个实例状态的方法都应该是非静态的,因为将它们设置为静态并手动传递实例不会获得任何性能。

为了说明这一点,你应该这样做

private void AddCount(int number) {
    current += number;
}

而不是这个:

// Do not do this!
private static void AddCount(MyClass obj, int number) {
    obj.current += value;
}
于 2013-05-14T13:46:19.413 回答
1

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

作为基本的一般规则,我不会将变量或函数设为静态,除非它对类的所有实例都至关重要。当然也有例外,但如果你只是无缘无故地将所有私有方法设为静态,那么你很可能会违反 OOP 范式。

于 2013-05-14T13:51:48.250 回答
0

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

于 2013-05-14T13:44:06.933 回答
0

我认为至少将方法定义为静态方法以明确它们不需要来自实例的数据是非常有用的。也就是说,我更喜欢非成员函数。查看Class design vs. IDE:nonmember nonfriend 函数真的值得吗?.

于 2013-05-14T13:46:03.813 回答
0

想到两个原因:

  1. 您不能访问您班级的其他非静态成员(如上所述)
  2. 您不能覆盖子类中的静态方法

IMO,静态方法应该更多地作为一个例外。如果您想“轻松访问”具有依赖注入容器的应用程序中的功能,最好使用单例 bean 并注入它,因为如果需要,您仍然可以选择轻松切换实现。

.NET 有一个静态方法的特定用例 - 扩展方法。因此,如果您希望您的功能可用作扩展方法,则必须使用静态。

于 2015-03-23T09:04:59.340 回答