如果私人帮手方法是静态的,那么它们应该是静态的

假设我有一个旨在实例化的类。 我在类中有几个私有的“helper”方法,它们不需要访问任何类成员,并且只对它们的参数进行操作,并返回结果。

public class Example {
   private Something member;

   public double compute() {
       double total = 0;
       total += computeOne(member);
       total += computeMore(member);
       return total;         
   }

   private double computeOne(Something arg) { ... }
   private double computeMore(Something arg) {... } 
} 

是否有任何特定的原因来指定computeOnecomputeMore作为静态方法 - 或者任何特定的原因?

将它们保持为非静态是最容易的,尽管它们当然可以是静态的而不会造成任何问题。


我更喜欢这样的辅助方法是private static ; 这将使读者清楚他们不会修改对象的状态。 我的IDE也会以斜体显示对静态方法的调用,所以我会知道该方法是静态的,不会看到签名。


它可能会导致稍小的字节码,因为静态方法无法访问this 。 我不认为它在速度上有什么不同(如果是这样,它可能会太小而无法在整体上有所作为)。

我会让它们变成静态的,因为我一般都会这样做,如果可能的话。 但那只是我。


编辑:这个答案不断下调,可能是因为字节码大小的未经证实的断言。 所以我会实际运行一个测试。

class TestBytecodeSize {
    private void doSomething(int arg) { }
    private static void doSomethingStatic(int arg) { }
    public static void main(String[] args) {
        // do it twice both ways
        doSomethingStatic(0);
        doSomethingStatic(0);
        TestBytecodeSize t = new TestBytecodeSize();
        t.doSomething(0);
        t.doSomething(0);
    }
}

字节码(用javap -c -private TestBytecodeSize检索):

Compiled from "TestBytecodeSize.java"
class TestBytecodeSize extends java.lang.Object{
TestBytecodeSize();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

private void doSomething(int);
  Code:
   0:   return

private static void doSomethingStatic(int);
  Code:
   0:   return

public static void main(java.lang.String[]);
  Code:
   0:   iconst_0
   1:   invokestatic    #2; //Method doSomethingStatic:(I)V
   4:   iconst_0
   5:   invokestatic    #2; //Method doSomethingStatic:(I)V
   8:   new     #3; //class TestBytecodeSize
   11:  dup
   12:  invokespecial   #4; //Method "<init>":()V
   15:  astore_1
   16:  aload_1
   17:  iconst_0
   18:  invokespecial   #5; //Method doSomething:(I)V
   21:  aload_1
   22:  iconst_0
   23:  invokespecial   #5; //Method doSomething:(I)V
   26:  return

}

调用静态方法需要两个字节码(字节?): iconst_0 (用于参数)和invokestatic
调用非静态方法有三个: aload_1 (对于TestBytecodeSize对象,我想), iconst_0 (对于参数),和invokespecial 。 (请注意,如果这些都没有私有方法,它会一直invokevirtual代替invokespecial ;见JLS§7.7调用方法。)

现在,正如我所说,除了invokestatic需要少一个字节码之外,我不认为这两者之间的性能会有很大差异。 invokestaticinvokespecial都应该是比稍快invokevirtual ,因为它们都使用静态绑定,而不是动态的,但我不知道如果任一比其他快。 我也找不到任何好的参考。 我能找到的最接近的是1997年的JavaWorld文章,它基本上重申了我刚才所说的内容:

最快的指令最有可能是invokespecialinvokestatic ,因为这些指令调用的方法是静态绑定的。 当JVM解析这些指令的符号引用并用直接引用替换它时,该直接引用可能会包含指向实际字节码的指针。

但自1997年以来,许多事情已经改变

所以最后......我想我仍然坚持我之前说过的话。 速度不应该是选择其中一个的理由,因为它最好是一个微型优化。


我个人的偏好是宣布它们是静态的,因为它是一个明确的标志,表明它们是无状态的。

链接地址: http://www.djcxy.com/p/17293.html

上一篇: Should private helper methods be static if they can be static

下一篇: What is the lifetime of a static variable in a C++ function?