使用静态私有方法真的比实例私有方法更快/更好吗?

时间:2013-03-05 14:38:35

标签: java performance coding-style static-methods

我要问的是这样做是否有区别:

public Something importantBlMethod(SomethingElse arg) {
    if (convenienceCheckMethod(arg)) {
        // do important BL stuff
    }
}

private boolean convenienceCheckMethod(SomethingElse arg) {
    // validate something
}

而且:

public Something importantBlMethod(SomethingElse arg) {
    if (convenienceCheckMethod(arg)) {
        // do important BL stuff
    }
}

private static boolean convenienceCheckMethod(SomethingElse arg) {
    // validate something
}

我实际上使用选项1,因为它对我来说似乎更自然。

第一种和第二种方式之间是否有样式/约定/性能差异?

谢谢,


正如我在测试中所建议的那样,在我的基准测试中,动态方法更快。

这是测试代码:

public class Tests {

    private final static int ITERATIONS = 100000;

    public static void main(String[] args) {
        final long start = new Date().getTime();

        final Service service = new Service();
        for (int i = 0; i < ITERATIONS; i++) {

            service.doImportantBlStuff(new SomeDto());
        }

        final long end = new Date().getTime();

        System.out.println("diff: " + (end - start) + " millis");
    }
}

这是服务代码:

public class Service {

    public void doImportantBlStuff(SomeDto dto) {

        if (checkStuffStatic(dto)) {

        }

        // if (checkStuff(dto)) {

        // }
    }

    private boolean checkStuff(SomeDto dto) {
        System.out.println("dynamic");
        return true;
    }

    private static boolean checkStuffStatic(SomeDto dto) {
        System.out.println("static");
        return true;
    }
}

对于100000次迭代,动态方法传递577ms,静态615ms。

然而,这对我来说是不确定的,因为我不知道编译器何时以及何时决定优化。

这是我想要找到的。

8 个答案:

答案 0 :(得分:7)

表现明智:差异(如果有的话)可以忽略不计。

经验法则是如果方法不与其类的任何成员交互,则声明您的方法是静态的。

答案 1 :(得分:2)

如果您的方法需要实例数据或调用其他实例方法,则必须是实例方法。

如果函数 only 依赖于它的参数,而没有其他静态数据,那么它也可能是一个实例方法 - 你可以避免在调用时重复类名静态功能。

恕我直言,除非:

,否则不需要制作函数static
  1. 它可以从其他类调用(即不是private)和
  2. 它不引用实例变量,而
  3. 它指的是其他静态类数据

答案 2 :(得分:2)

如果函数的结果不依赖于除参数之外的任何东西,它应该是静态的。如果它依赖于实例,请将其设为实例成员。

这不是关于表现;这是关于语义的。除非你每秒钟调用这个函数一百万次,否则你不会注意到性能差异,即使这样,差异也不会很大。

答案 3 :(得分:2)

这完全取决于具体情况。通常,静态方法/变量在类中声明,以便外部类可以使用它们。

如果要调用本地方法,那么通常应该使用实例方法而不是静态调用。

仅供参考,您从实例方法调用静态方法的语法是错误的。你必须提供班级名称。

答案 4 :(得分:2)

据我所知 NO 静态方法的绑定与非静态私有绑定相同,即early binding。 。 编译器实际上在为代码添加方法代码(静态或非静态私有)时创建它的字节代码。

更新:刚刚通过此article。它说实例方法绑定是dynamic所以如果方法不是non-static private那么。 静态方法更快

答案 5 :(得分:2)

可能,它可能不会。不同的代码执行可能会有所不同。

如果不深入研究Hotsport代码(或非Hotspot JVM的代码),这是唯一可以知道的东西:

  • 使用invokestatic调用静态方法,该方法不需要对象引用。
  • 使用invokespecial调用实例私有方法,它需要对象引用。

这两个操作码都有一个解析实际调用方法的过程,这些过程相对类似(你可以阅读规范)。如果不计算实际实现的指令,就不可能说哪个更快。

invokespecial将额外的值推入堆栈。这样做的时间以几纳秒计算。

尽管如此,Hotspot还是可以进行各种优化。在程序运行期间,它可能不必多次执行实际的方法解析。它可能会选择内联方法(或者可能不会),但是这个成本将再次大致相当。

答案 6 :(得分:1)

我查了一下,我希望它可以做你想知道的,代码不会很漂亮:

public class main {

@SuppressWarnings("all")
public static void main(String[] args) {
    main ma = new main();
    int count = Integer.MAX_VALUE;
    long beg = (new Date()).getTime();
    for (int i = 0; i < count; i++) {
        ma.doNothing();
    }
    System.out.println("priv : " + new Long((new Date()).getTime() - beg).toString());

    beg = (new Date()).getTime();
    for (int i = 0; i < count; i++) {
        doNothingStatic();
    }
    System.out.println("privstat : " + new Long((new Date()).getTime() - beg).toString());

}

private void doNothing() {
    int i = 0;
}

private static void doNothingStatic() {
    int i = 0;
}
}

结果:

priv:1774
privstat:1736

priv:1906年 privstat:1783

priv:1963年 privstat:1751

priv:1782
privstat:1929年

私有:1876年 privstat:1867年

它看起来不像静态 - 非静态私有方法。我确信这些差异来自当前的机器负担。

答案 7 :(得分:1)

我参与编码竞赛,我观察到,非静态方法比静态方法更快(但是最小)。当然,这取决于您的使用情况和情况需求,但静态方法与非静态方法相比性能较差。按照惯例,您可以使用静态方法来简化代码,但创建类的实例并调用该方法将提供更好的性能。