哪一個更優化或者有什麼不同?這兩段代碼中的哪一段更好/更快/使用的內存更少?
String s = methodThatReturnsString();
int i = methodThatReturnsInt();
thirdMethod(s, i);
或
thirdMethod(methodThatReturnsString(), methodThatReturnsInt());
通過優化我的意思是在內存使用情況等的條件最佳
哪一個更優化或者有什麼不同?這兩段代碼中的哪一段更好/更快/使用的內存更少?
String s = methodThatReturnsString();
int i = methodThatReturnsInt();
thirdMethod(s, i);
或
thirdMethod(methodThatReturnsString(), methodThatReturnsInt());
通過優化我的意思是在內存使用情況等的條件最佳
它沒有任何這裏做優化,但它的可讀性的更多問題您代碼...
絕對,但請記住,人們可能會對第一或第二是否更具可讀性持不同意見。 – 2010-01-14 12:11:34
是的,你說得對。但是,這裏仍然是一個可讀性問題;) – romaintaz 2010-01-14 12:32:03
完全沒有區別。在這種情況下,您可能需要考慮可讀性和清晰度。
哪一個更優化?
的其中一個更容易閱讀:-)
我認爲編譯時的差額優化掉(前提是聲明的變量不使用之後 - 即解決方案,否則相同的)。
應該沒有什麼區別。臨時使用的String
和int
都必須駐留在某處,Java在內部是堆棧機器。因此,無論您是否給該方法的返回值調用名稱,都必須在執行thirdMethod(String, int)
之前將其存儲在堆棧中。
對於生成的JITted代碼的影響可能很難找到。這是一個完全不同的抽象層次。
如果有疑問,簡介。但我不希望這裏有任何不同。
這是同樣的事情。在這兩種情況下,將調用相同的函數,並且變量(自動或顯式定義將被分配)。唯一的區別是在第二種情況下,變量將準備好垃圾回收,而在第一種情況下,您需要等待超出範圍。
但是,當然第一個更可讀。
-1有關GC的聲明不正確。實際上,直到方法退出才真正收集到任何東西。 (使用新的openJDK) – 2010-01-15 00:23:50
是的,但在第一個版本中,變量s和i即使在方法退出後也不會被垃圾回收。將發生什麼取決於包裝代碼。 – kgiannakakis 2010-01-15 05:47:47
我寧願選擇第一個選項。然而,這與速度無關,但具有可調試性。在第二個選項中,我不能輕易檢查s
和i
的值。在性能方面,這根本不會有任何改變。
我高度懷疑這兩種形式是相同的,但不要拿我的這個詞。讓我們找出自己! :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()
是不同。它看起來像編譯器正在添加調試符號。也許這是迫使它明確地分配返回值給局部變量,引入額外的指令。
讓我們嘗試用重新編譯沒有調試:
> 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),字節碼對於第二個版本而言較短。但是,虛擬機可能會優化任何差異。 :)
編輯:約阿希姆·紹爾的評論的一些額外的澄清禮貌:它是如何 實際執行上取決於很多:
需要注意的是字節 代碼告訴只是故事的一半是非常重要的 JVM(與 C/C++完全不同,在這裏你可以看到彙編程序 的代碼,它正是如何執行它的 )。我想你認識到, 但我認爲它應該在帖子中更明確 。
需要注意的是,字節碼只告訴了一半:它的實際執行方式很大程度上取決於JVM(這與C/C++完全不同,在C/C++中,您可以看到彙編代碼以及它的執行方式)。我認爲你意識到這一點,但我認爲這個帖子應該更清楚。 – 2010-01-14 12:37:16
@Joachim:我完全同意!我已將您的評論添加到答案中。 – 2010-01-14 12:47:13
++花時間穿過它。我*沒有聽到的唯一的事情就是有人說,差異的相關性取決於函數內部的工作量。對於典型的功能,您發現的差異可能很容易產生噪音。 – 2010-01-14 14:32:59
實驗和測量。如果速度是關鍵,那麼測量速度。如果內存使用量很重要,請測量內存使用情況如果字節碼指令的數量非常重要,請對字節碼指令進行計數。如果代碼的可讀性是重要的,那麼測量代碼的可讀性。弄清楚如何衡量代碼的可讀性是你的功課。
如果你不試驗和測量所有你會得到的意見和論點。或者,如果你非常幸運,SO上的某個人會爲你運行你的實驗。
PS這篇文章當然是我的觀點和論點
如果有差異,那就不值得煩惱了。 – Yacoby 2010-01-14 11:54:07
而且所說的區別將取決於所使用的編譯器。編譯器優化甚至可能會導致完全相同的代碼,如果之後沒有使用s和i。我會根據可讀性做出我的決定。 – Stroboskop 2010-01-14 11:55:54
您可以嘗試編譯並比較字節代碼 – lexicalscope 2010-01-14 12:05:35