如果我有一个类,我希望在一个对内存敏感的应用程序中的数千个实例中使用它,如果我将静态功能分解为静态成员会有帮助吗?
我想静态方法和变量每个类存储一次,而对于非静态成员,必须为每个实例存储一些东西。
使用成员变量,似乎很清楚,但是为方法存储了哪种数据?
我在Java工作,但我想象一些适用于其他托管环境(如.NET)的一般规则。
答案 0 :(得分:18)
静态方法和幕后非静态(实例)方法之间的唯一区别是,一个额外的隐藏参数(this
)被传递给实例方法,并且可以使用间接调度来调用实例方法(如果是虚拟的)。没有额外的代码空间。
编辑:
我的回答集中在方法上,但仔细阅读后我发现问题更多的是关于静态数据。是的,静态数据在某种意义上会节省内存,因为它只有一个副本。当然,数据是否应该是静态的更多地取决于数据的含义或用途,而不是节省内存。
如果您需要拥有大量对象并希望节省内存,您可能还需要调查是否适用'Flyweight' pattern。
答案 1 :(得分:16)
不应以效率为由做出决定 - 应以正确性为依据。
如果您的变量代表每个实例的不同值,那么它应该是一个实例变量。
如果您的变量是与该类型相关联的公共值而不是该类型的单个实例,则它应该是一个静态变量。
然而,你是正确的 - 如果你有一个静态变量,你不会为每个实例“支付”。这只是增加了一个额外的理由,使变量在不代表对象状态的一部分时保持静态。
当你提到问题中的方法时,你在谈论局部变量吗?您将为每个方法调用获得一组新的局部变量 - 包括递归调用。但是,这不会创建一组新的静态或实例变量。
答案 2 :(得分:4)
简单的答案是肯定的。每次创建实例都没有等于重新创建整个对象,静态方法和变量通常会消耗更少的内存,具体取决于它们的使用方式。当然,如果您只需要在整个程序中创建一个实例,那就没有区别了。并且请记住,您始终可以将实例作为引用传递给不能有静态对象的引用,并且需要重用它们。
答案 3 :(得分:3)
如果你将一个成员变量设为静态,你可以节省每个实例的内存(假设有多个实例),但真正的好处是你不必努力保持所有那些非静态成员与每个实例一致。另外,您不需要当前实例来访问静态成员。
如果你创建一个静态方法,你可以为每个嵌套调用在堆栈上保存几个字节(没有隐含的'this'参数),但这只有在你做非常重的情况下才有意义递归。当然,如果函数需要知道你正在处理哪个实例,那么你需要一个显式参数来替换隐含的'this',所以你什么也得不到。
使用静态方法或非静态方法没有每个实例的成本。费用发生在电话上。
使用静态方法的真正原因是因为没有实例 - 至少在您调用方法时。例如,您可以使用静态方法来创建和初始化实例(“工厂”设计模式之一),或引用单例实例。