2

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

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 次迭代,动态方法通过 577 毫秒,静态方法通过 615 毫秒。

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

这就是我想要找出的。

4

8 回答 8

7

性能方面:差异(如果有的话)可以忽略不计。

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

于 2013-03-05T14:41:40.487 回答
2

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

如果函数依赖于它的参数,而不依赖于其他静态数据,那么它也可能是一个实例方法——您将避免在调用静态函数时需要重复类名。

恕我直言,没有特别需要制作该功能static,除非:

  1. 它可以从其他类(即 not private)调用,并且
  2. 它不引用实例变量,并且
  3. 它引用其他静态类数据
于 2013-03-05T14:41:32.940 回答
2

如果函数的结果不依赖于参数以外的任何东西,它应该是静态的。如果它依赖于实例,则使其成为实例成员。

这与性能无关;这是关于语义的。除非您每秒调用此函数一百万次,否则您不会注意到性能差异,即使那样差异也不会很大。

于 2013-03-05T14:42:31.440 回答
2

这一切都取决于上下文。通常静态方法/变量在类中声明,以便外部类可以使用它们。

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

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

于 2013-03-05T14:44:23.913 回答
2

根据我的说法,静态方法的NO绑定与非静态私有 ie 相同early binding。. 编译器实际上在创建字节码时将方法代码(静态或非静态私有)添加到您的代码中。

更新:刚刚通过这篇文章。它说实例方法绑定是dynamic如此,如果方法不是non-static private那么。您的静态方法更快

于 2013-03-05T14:45:33.023 回答
2

可能会,也可能不会。您的代码的不同执行之间可能会有所不同。

这是您无需深入研究 Hotsport 代码(或非 Hotspot JVM 的代码)即可知道的唯一一件事:

  • 静态方法使用invokestatic调用,不需要对象引用。
  • 实例私有方法是用invokespecial调用的,它确实需要一个对象引用。

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

invokespecial一个额外的值压入堆栈。执行此操作的时间以几分之一纳秒计算。

Hotspot 可以执行的优化范围很广。在程序运行期间,它可能不必多次执行实际的方法解析。它可能会选择内联该方法(也可能不内联),但该成本将再次大致相等。

于 2013-03-05T15:05:53.620 回答
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;
}
}

结果:

私人:1774
私人统计:1736

私人:1906
私人统计:1783

私人:1963
私人统计:1751

私人:1782
私人统计:1929

私人:1876
私人统计:1867

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

于 2013-03-05T15:38:27.720 回答
1

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

于 2015-06-11T11:20:43.157 回答