【问题标题】:Static members vs instance members静态成员与实例成员
【发布时间】:2015-08-23 13:19:45
【问题描述】:

如果我只需要声明一些常量以在我的类中使用,并且没有真正需要将它们声明为静态的,即不会有多个实例共享该成员,那么将它们声明为静态有什么意义吗?使用静态成员和实例成员之间是否存在“成本差异”?请提供有关 java 和 C# 的信息。

另外,java的静态成员和C#的静态成员有区别吗?

【问题讨论】:

  • 我不了解 Java,但在 C# 中,常量本质上是静态的 (reference)。这对我来说似乎很直观;拥有实例级常量有什么意义?
  • 据我所知,在 Java 中,静态变量存储在 PermGen 空间中,而实例变量存储在堆中(PermGen 空间是一种特殊的堆,其中包含所有已加载的类及其方法的蓝图以及静态变量定义)。通常较大的应用程序服务器会遇到这个问题,但对于小型应用程序来说,这是可以忽略的。对于 C#,请参阅 this link
  • @RomanVottner 是关于 java 还是 c# 的?

标签: java c# static-members


【解决方案1】:

在 Java 中,常量不是隐式静态的;常量不是一个实际的语言规范,所以 Java 中的常量只是我们称之为常量的变量。

在 C# 中,常量隐式静态的。常量是语言规范的一部分,并在documentation 中声明:

常量的访问就像它们是静态字段一样,因为常量的值对于该类型的所有实例都是相同的。您不使用 static 关键字来声明它们。

【讨论】:

    【解决方案2】:

    如果你将常量声明为静态,那么你的程序将只使用一个内存位置来存储这个常量值,如果你不使用静态,那么每个对象都会单独存储这个常量。正如您所说,没有几个实例,在这种情况下,您要么将常量指定为静态,要么简单地声明它,两者的成本相同。

    【讨论】:

      【解决方案3】:

      出于多种原因,我通常将应用程序中的每个常量都声明为 private static final 变量。

      1. 一致性。我自己和其他人都清楚我的应用程序中的默认核心常量定义是什么。我可以将它们全部组合在一起,如果需要修改它们很容易导航到它们。因为他们是static,所以这些变化会在每次通话中蔓延。这可以防止您意外地对同一个常量进行多个定义。
      2. 性能。如果我有一个从未更改过的常量,那么在方法调用期间不断为它分配内存是没有意义的。它在引用类时分配一次,然后你就完成了。在所有对该类的引用完成之前,该内存仍然是引用。
      3. 良好实践。 编程中有一个约定,其中的依赖项应尽可能高度解耦。当您将函数或变量声明为 static 时,您强制要求它必须以静态方式进行交互,即独立于运行时实例。如果没有在运行时封装成员变量的类的这种依赖关系,您可以更精确地控制与该类的交互,因为它确保您定义关于如何与类交互的精确规则。您会发现,您可以声明为 static 的常量和方法越多,您的软件就越灵活,因为对于应该如何操作某些值和行为几乎没有混淆。
      4. 暴露。您定义的某些函数或常量可能对您的应用程序的其他部分有用。这意味着您可以利用功能而无需使用运行时实例。例如,二次公式在任何地方都是相同的,那么它为什么要属于单个实例呢?常数也是如此,比如光速。

      就个人而言,我总是将我的应用程序的所有功能声明为private static。如果一个类使用该功能作为其操作的一部分是有意义的,那么程序员可以将方法调用包装在另一个方法中并提供适当的成员变量数据。如果您的应用程序的另一部分需要使用该静态函数,您需要做的就是增加该函数的可见性。

      【讨论】:

      • 啊,真的。唉,这就是我失败的地方。我会说const 可能与final 相同,但我对语义的了解还不够,无法提供准确的解释!
      • 在 C# 中你可能想使用private static readonlyprivate const
      【解决方案4】:

      我只需要声明一些要在我的类中使用的常量

      不知道Java,但在C# 中,常量成员本质上隐含static

      请参阅MSDN Document: Constants (C# Programming Guide) 了解更多信息。引用参考文件:

      常量被当作static 字段访问,因为值 对于该类型的所有实例,常量的值都是相同的。你不 使用static 关键字来声明它们。

      【讨论】:

      • 常量在 Java 中不是隐式静态的
      • 很高兴知道但不知道Java
      • 是的,我知道,我只是在澄清“不确定 Java”——Java 中唯一的隐式静态成员是在接口中声明的字段(隐式静态最终)。将其编辑为您的答案,我将删除我的 cmets。我不是说你是否知道;我告诉你,这样你就可以将它包含在你的答案中。
      • @VinceEmigh,别担心;如果它增值,请随时(将来)随时编辑我的答案。
      猜你喜欢
      • 2019-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多