这两段代码中的哪一块更好/更快/使用更少的内存?

时间:2010-01-14 11:52:05

标签: java optimization

哪一个更优或者是否有任何差异?

String s = methodThatReturnsString();
int i = methodThatReturnsInt();
thirdMethod(s, i);

thirdMethod(methodThatReturnsString(), methodThatReturnsInt());

通过最优,我的意思是在内存使用等方面最优。

9 个答案:

答案 0 :(得分:15)

这与优化无关,但更多的是你的代码的可读性问题......

答案 1 :(得分:11)

  

哪一个更优化?

更易于阅读的内容: - )

我认为任何差异都会在编译时被优化掉(前提是之后不使用声明的变量 - 即解决方案在其他方面相同)。

答案 2 :(得分:10)

我非常怀疑这两种形式是相同的,但不要将我的字用于它。让我们发现自己! :d

public class Tests {

    public void test1() {
        String s = methodThatReturnsString();
        int i = methodThatReturnsInt();
        thirdMethod(s, i);
    }

    public void test2() {
        thirdMethod(methodThatReturnsString(), methodThatReturnsInt());
    }

    public String methodThatReturnsString() {
        return "";
    }

    public int methodThatReturnsInt() {
        return 0;
    }

    public void thirdMethod(String s, int i) {

    }

}

让我们编译它:

> javac -version
javac 1.6.0_17

> javac Tests.java

现在,让我们打印出字节码指令!

> javap -c Tests
Compiled from "Tests.java"
public class Tests extends java.lang.Object{
public Tests();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."":()V
   4:   return

public void test1();
  Code:
   0:   aload_0
   1:   invokevirtual   #2; //Method methodThatReturnsString:()Ljava/lang/String;
   4:   astore_1
   5:   aload_0
   6:   invokevirtual   #3; //Method methodThatReturnsInt:()I
   9:   istore_2
   10:  aload_0
   11:  aload_1
   12:  iload_2
   13:  invokevirtual   #4; //Method thirdMethod:(Ljava/lang/String;I)V
   16:  return

public void test2();
  Code:
   0:   aload_0
   1:   aload_0
   2:   invokevirtual   #2; //Method methodThatReturnsString:()Ljava/lang/String;
   5:   aload_0
   6:   invokevirtual   #3; //Method methodThatReturnsInt:()I
   9:   invokevirtual   #4; //Method thirdMethod:(Ljava/lang/String;I)V
   12:  return

public java.lang.String methodThatReturnsString();
  Code:
   0:   ldc     #5; //String
   2:   areturn

public int methodThatReturnsInt();
  Code:
   0:   iconst_0
   1:   ireturn

public void thirdMethod(java.lang.String, int);
  Code:
   0:   return

}

我觉得这看起来有点奇怪 - test1()test2() 不同。看起来编译器正在添加调试符号。也许这迫使它明确地将返回值分配给局部变量,引入额外的指令。

让我们尝试使用 no 调试重新编译它:

> javac -g:none Tests.java
> javap -c Tests
public class Tests extends java.lang.Object{
public Tests();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."":()V
   4:   return

public void test1();
  Code:
   0:   aload_0
   1:   invokevirtual   #2; //Method methodThatReturnsString:()Ljava/lang/String;
   4:   astore_1
   5:   aload_0
   6:   invokevirtual   #3; //Method methodThatReturnsInt:()I
   9:   istore_2
   10:  aload_0
   11:  aload_1
   12:  iload_2
   13:  invokevirtual   #4; //Method thirdMethod:(Ljava/lang/String;I)V
   16:  return

public void test2();
  Code:
   0:   aload_0
   1:   aload_0
   2:   invokevirtual   #2; //Method methodThatReturnsString:()Ljava/lang/String;
   5:   aload_0
   6:   invokevirtual   #3; //Method methodThatReturnsInt:()I
   9:   invokevirtual   #4; //Method thirdMethod:(Ljava/lang/String;I)V
   12:  return

public java.lang.String methodThatReturnsString();
  Code:
   0:   ldc     #5; //String
   2:   areturn

public int methodThatReturnsInt();
  Code:
   0:   iconst_0
   1:   ireturn

public void thirdMethod(java.lang.String, int);
  Code:
   0:   return

}

不可思议!

因此,根据我的编译器(Sun JDK),第二个版本的字节码更短。但是,虚拟机可能会优化任何差异。 :)

编辑:一些额外的澄清礼貌由Joachim Sauer的评论提供:

  

重要的是要注意字节   代码只讲述了一半的故事:它是怎么回事   实际执行取决于很多   JVM(与...完全不同)   C / C ++,您可以在其中看到汇编程序   代码,它正是如此   执行)。我想你意识到了,   但我认为应该更清楚   在帖子里。

答案 3 :(得分:6)

我更喜欢第一种选择。然而,这与速度无关,但具有可调试性。在第二个选项中,我无法轻松检查si的值。在性能方面,这根本没有任何区别。

答案 4 :(得分:1)

应该没有任何区别。暂时使用的Stringint都必须驻留在某处,Java在内部是堆栈计算机。因此,无论您是否给出该方法的返回值调用名称,都必须在执行thirdMethod(String, int)之前将它们存储在堆栈中。

对于生成的JITted代码的含义很难找到。这是一个完全不同的ob抽象层次。

如有疑问,请说明。但我不希望这里有任何不同。

答案 5 :(得分:1)

这是一回事。在这两种情况下,将调用相同的函数并且将分配变量(自动或显式定义)。唯一的区别是,在第二种情况下,变量将准备好进行垃圾回收,而在第一种情况下,您需要等待超出范围。

当然,第一个更具可读性。

答案 6 :(得分:0)

完全没有区别。在这种情况下,您可能需要考虑可读性和清晰度。

答案 7 :(得分:0)

实验和测量。如果速度是重要的,那么测量速度。如果内存使用很重要,请测量内存使用量如果字节码指令的数量很重要,则计算字节码指令。如果代码可读性很重要,请测量代码的可读性。确定如何衡量代码可读性是你的功课。

如果你没有进行实验和测量,那么你将获得意见和论证。

或者,如果你很幸运,SO上的某个人会为你运行实验。

PS这篇文章当然是我的观点和论点

答案 8 :(得分:-2)

thirdMethod(metodThatReturnsString(),metodThatReturnsInt());

更优化......