Which of those two pieces of code is better/faster/uses less memory?
Which one is more optimal or is there any difference at all?
String s = methodThatReturnsString();
int i = methodThatReturnsInt();
thirdMethod(s, i);
or
thirdMethod(methodThatReturnsString(), methodThatReturnsInt());
By optimal I mean optimal in the te开发者_JAVA技巧rms of memory usage etc.
It has nothing to do with optimization here, but it's more a question of readability of your code...
Which one is more optimal?
The one which is easier to read :-)
I would think that any difference is optimized away when compiled (provided that the declared variables are not used afterwards - i.e. the solutions are otherwise identical).
I highly suspect that both forms are identical, but don't take my word for it. Let's find out ourselves! :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) {
}
}
Let's compile it:
> javac -version javac 1.6.0_17 > javac Tests.java
Now, let's print out the bytecode instructions!
> 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 }
I thought this looked a bit strange - test1()
and test2()
are different. It looks like the compiler is adding the debugging symbols. Perhaps this is forcing it to explicitly assign return values to the local variables, introducing extra instructions.
Let's try recompiling it with no debugging:
> 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 }
Inconceivable!
So, according to my compiler (Sun JDK), the bytecode is shorter for the second version. However, the virtual machine will probably optimize any differences away. :)
Edit: Some extra clarification courtesy of Joachim Sauer's comment:
It's important to note that the byte code tells only half the story: How it is actually executed depends a lot on the JVM (that's quite different to C/C++, where you can see the assembler code and it's exactly how it's executed). I think you realize that, but I think it should be made clearer in the post.
I would prefer the first option. However this has nothing to do with speed, but with debuggability. In the second option I can not easily check what the values of s
and i
are. Performance-wise this will not make any difference at all.
There shouldn't be any difference. Both the temporarily used String
and int
have to reside somewhere and Java is, internally, a stack machine. So regardless of whether you give the return values of that method calls names or not, they have to be stored on the stack prior to execution of thirdMethod(String, int)
.
Implications of that for the resulting JITted code can be hard to find. That's on a completely different level ob abstraction.
If in doubt, profile. But I wouldn't expect any difference here.
It is the same thing. In both cases the same functions will be called and variables (automatic or explicitly defined will be allocated). The only difference is that in the second case, the variables will be ready to garbage collected whereas on the first one you need to wait to get out of scope.
Of course however the first one is much more readable.
There is no difference at all. In this case, you might want to consider readability and clearness.
Experiment and measure. If speed is what matters, measure speed. If memory usage matters, measure memory usage. If number of bytecode instructions is what matters, count bytecode instructions. If code readability is what matters, measure code readability. Figuring out how to measure code readability is your homework.
If you don't experiment and measure all you get will be opinion and argument.
Or, if you are very lucky, someone on SO will run your experiments for you.
PS This post is, of course, my opinion and argument
thirdMethod(metodThatReturnsString(), metodThatReturnsInt());
is more optimal...
精彩评论