我知道什么是静态的,但不确定何时使用它。
静态变量:我只将其用于常量字段。有时一个类中有几十个常量,因此使用静态常量可以节省大量内存。还有其他典型用例吗?
静态方法:我在上关于算法的课程时会使用它。例如,提供不同排序算法的类。是否违反OOP设计?我认为最好保持这种方式,而不是在需要使用它们的每个类中实现排序算法。我错了吗?有哪些好的用例?
而且,使用静态和非静态字段/方法之间是否有性能差异?
[您正在描述使用静态方法的情况,但这并不能从根本上解释为什么使用静态方法还是使用非静态方法的原因-它们不仅仅是常量和实用程序方法的关键字。
[如果某事物不是静态的(实例),则意味着该类的每个实例都有一个实例。每个人都可以独立更改。
当某个事物是静态的时,它意味着该类的所有实例只有一个副本,因此从任何位置进行更改都会影响所有其他。
静态变量/方法通常使用较少的内存,因为它们只有一个副本,而不管您有多少个类实例。静电,如果使用得当,在面向对象的设计中就非常好。
[如果您有一个方法/变量,而您只需要一个实例(例如,常量或实用程序方法),则只需使其静态即可。了解将方法设为静态意味着无法覆盖它。因此,如果您有要在子类中覆盖的方法,请不要使其变为静态。
一般的经验法则是-如果只需要一个副本,请将其设为静态。如果您需要每个实例一个副本,则使其成为非静态。
还有其他典型用例吗?
全局变量
是否违反OOP设计?
并不确切,关键是静态方法是无状态的,因为您不需要类的特定实例。我最喜欢的方法是实用程序方法(例如Apache Commons)。但是,您可能会意识到,某些方法最好作为类成员而不是静态方法。
一旦您无法覆盖这些方法或用模拟实现代替,静态方法也会使类的可测试性变得更难。
性能差异?
[Google有一项性能建议,说“静态优先于虚拟”:
http://developer.android.com/training/articles/perf-tips.html#PreferStatic
由于Android使用不同的VM,因此我不确定JVM是否适用,但是鉴于链接指出的原因,这是有道理的:
如果您不需要访问对象的字段,请将您的方法设为静态。调用速度将提高约15%-20%。这也是一个好习惯,因为您可以从方法签名中得知调用该方法不能更改对象的状态。“
我个人的经验法则是,静态事物“只是在外面闲逛”。它们是全球性的(免责声明,并非完全正确),但是将其包含在这一类中是有意义的。
如果您发现自己反复加载一些重量级的对象,则静态字段会很好。例如,我正在处理的项目现在在两个图像之间切换。这些是静态字段,它们随应用程序一起加载并保留在内存中,而不是每次都重新加载它们并让GC负责处理。
除了非常特殊的情况,我仅将静态(和最终)变量用于常量。当然,使用它们完全合法。
我倾向于避免使用静态实用程序方法,因为它们使编写代码的单元测试变得更加困难(模拟方法调用的结果)。当您开始开发“测试驱动”方式时,此问题变得很明显。我更喜欢使用依赖项注入和单例bean(尽管这取决于您的需求和情况)。
静态变量属于一个类,因此由所有对象共享,因此,如果您确实希望共享该变量,则内存使用量会减少。如果您将变量声明为public和static,那么每个人都可以使用它。
静态方法通常是实用程序方法,具体取决于访问修饰符,它们可以在一个类中使用或在整个类中使用。静态实用程序类将有助于再次减少内存使用,因为您无需创建对象来调用这些方法。
您可以将静态字段用作实用程序。
仅是一个例子,假设我们需要知道我们有多少个实例:
类别Counter
public class Counter {
public static int instanceCount ;
public Counter()
{
instanceCount++;
}
public int getInstanceCount()
{
return instanceCount;
}
}
创建两个Counter
类的实例之后。但是它们共享相同的instanceCount
字段,因为它是一个静态字段,因此instanceCount
的值在firstCounter
和secondCounter
中将变为相同。
Class main
Counter firstCounter = new Counter();
// will print 1
System.out.println(co.getInstanceCount());
// will print 2
Counter secondCounter = new Counter();
System.out.println(co1.getInstanceCount());