何时使用静态方法和字段?

时间:2013-07-12 18:55:25

标签: java performance oop static

我知道什么是静电,但不知道何时使用它。

静态变量: 我只用它来做恒定的场。有时候类中有几十个常量,所以使用静态常量可以节省大量内存。还有其他典型的用例吗?

静态方法: 我在制作关于算法的课时使用它。例如,提供不同排序算法的类。它是否反对OOP设计?我认为保持这种方式比在每个需要使用它们的类中实现排序算法更好。我错了吗?什么是好用例?

此外,使用静态和非静态字段/方法之间是否存在性能差异?

6 个答案:

答案 0 :(得分:18)

您正在描述使用静态的情况,但这并不能完全解释为什么要使用静态和非静态 - 它们不仅仅是常量和实用方法的关键字。

当某些东西不是静态的(实例)时,它意味着每个类的实例都有一个实例。每个人都可以独立改变。

当某些东西是静态的时,意味着该类的所有实例只有一个副本,因此从任何位置更改它都会影响所有其他实例。

静态变量/方法通常使用较少的内存,因为它们只有一个副本,无论您拥有多少个类实例。如果使用得当,静力学在面向对象设计中非常精细。

如果你有一个方法/变量只需要一个实例(例如常量或实用方法),那么只需将其设为静态。理解虽然使方法静态意味着它不能被覆盖。因此,如果您想要在子类中覆盖一个方法,那么请不要将其设置为静态。

一般的经验法则是 - 如果您只需要一份副本,请将其设为静态。如果每个实例需要一个副本,则将其设置为非静态。

答案 1 :(得分:3)

还有其他典型用例吗?

全局变量

是否反对OOP设计?

不是很重要,重点是静态方法是无状态的,因为您不需要类的特定实例。我最喜欢的方法是实用程序方法(如Apache Commons)。但是您可能知道某些方法可能更适合作为类成员而不是静态。

一旦你无法覆盖这些方法或者通过模拟实现替换,静态方法也会使类可测试性变得更难。

性能差异?

Google提出的性能Android建议称“偏好静态虚拟化”:

http://developer.android.com/training/articles/perf-tips.html#PreferStatic

我不确定JVM是否属实,因为Android使用不同的VM,但考虑到链接指出的原因,它是有道理的:

  

如果您不需要访问对象的字段,请将方法设为静态。调用速度将提高约15%-20%。这也是一种很好的做法,因为你可以从方法签名中看出调用方法不能改变对象的状态。“

答案 2 :(得分:0)

静态变量属于一个类,因此由所有对象共享,因此如果您真的希望共享变量,则内存使用量会减少。如果您将变量声明为public和static,那么它将全局可供所有人使用。

静态方法通常是实用方法,取决于访问修饰符,可以在类中或跨类使用。静态实用程序类将有助于再次减少内存使用,因为您不需要创建对象来调用这些方法。

答案 3 :(得分:0)

我个人的经验法则是静态的东西“只是挂在那里”。它们(免责声明,并非完全真实)是全球性的,但包含在这个特定的类中是有意义的。

如果您发现自己反复加载一些重量级对象,静态字段就很好。例如,我正在进行的项目现在可以在两个图像之间切换。这些是随应用程序一起加载并保存在内存中的静态字段,而不是每次都重新加载它们并让GC处理这些混乱。

答案 4 :(得分:0)

除了非常具体的情况,我只使用静态(和最终)变量作为常量。当然,使用它们是完全有效的。

我倾向于避免使用静态实用程序方法,因为它们使得为代码编写单元测试变得更加困难(模拟方法调用的结果)。当您开始开发测试驱动方式时,此问题变得非常明显。我更喜欢使用依赖注入和单例bean(尽管这取决于你的需求和情况)。

答案 5 :(得分:0)

static field在所有对象中只有一个值,它们也称为Class成员,因为它与该类有关。

  • 您可以将静态字段用作实用程序。

    只是一个例子假设我们需要知道我们有多少个实例:

Counter

     public class Counter {


     public static int instanceCount ;

        public Counter()
        {
            instanceCount++;
        }

        public int getInstanceCount()
        {
            return instanceCount;
        }



    }

创建两个Counter类的实例之后。但是它们共享相同的instanceCount字段,因为它是一个静态字段,因此instanceCount的值在firstCountersecondCounter中将变为相同。

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());