Heim  >  Artikel  >  Java  >  Wie ist die Ausführungsreihenfolge von Return- und Final-Anweisungen in Java?

Wie ist die Ausführungsreihenfolge von Return- und Final-Anweisungen in Java?

PHPz
PHPznach vorne
2023-04-25 19:55:061873Durchsuche

Quellcode:

public class ReturnFinallyDemo {     public static void main(String[] args) {         System.out.println(case1());     }      public static int case1() {         int x;         try {             x = 1;             return x;         } finally {             x = 3;         }     } }  # 输出

Die Ausgabe des obigen Codes kann einfach schlussfolgern: return wird ausgeführt, bevor wir uns abschließend ansehen, was auf Bytecode-Ebene passiert. Das Folgende fängt einen Teil des Bytecodes der case1-Methode ab und vergleicht ihn mit dem Quellcode, um die Bedeutung jeder Anweisung zu kommentieren:

iconst_1 // 将常量1推入操作数栈顶  istore_0 // 弹出栈顶元素(1),保存到局部变量表slot[0],此时slot[0]=1。这两条指令对应源码:x = 1;  iload_0 // 将局部变量表slot[0]的值推入操作数栈顶,也就是说把上面x的值推入栈顶  istore_1 // 弹出栈顶元素(1),保存到局部变量表slot[1],此时slot[1]=1。其实,此时就已经把要return的值准备好了  iconst_3 // 将常量3推入操作数栈顶,这一条指令开始,其实是开始执行finally中的代码了  istore_0 // 弹出栈顶元素(3),保存到局部变量表slot[0],此时slot[0]=3。这两个指令对应源码:x = 3;这里要注意的是,虽然都是更新了x的值,但是finally中的x和try中x的赋值,保存在了不同的局部变量表中 iload_1 // 将局部变量表slot[1]的值推入操作数栈顶,此时栈顶元素的值为1,是第3行指令保存的值  ireturn // 将操作数栈顶的值返回给调用方

Aus dem Bytecode geht hervor, dass der endgültige Code zuerst ausgeführt wird, da es sich tatsächlich um die ireturn-Anweisung handelt in Es wird zuletzt ausgeführt, daher hängt der zurückgegebene Wert nicht davon ab, wer es zuerst ausführt, sondern davon, wann das oberste Element des von der ireturn-Anweisung zurückgegebenen Operandenstapels gespeichert wird. In der obigen Codeumgebung ist es die Version, die x im Try-Codeblock zugewiesen ist, dh die Version von x, die unmittelbar nach der Return-Anweisung gespeichert wird.

Sehen wir uns ein etwas komplizierteres Szenario an:

public static int case2() {     int x;     try {         x = 1;         return ++x;     } finally {         x = 3;     } }  # 输出

Mit der obigen Analyse ist dies leicht zu verstehen:

iconst_1 // 将常量1推入操作数栈顶 istore_0 // 弹出栈顶元素(1),保存到局部变量表slot[0],此时slot[0]=1。这两条指令对应源码:x = 1; iinc          0, 1 // 对局部变量表slot[0]进行自增(+1)操作,此时slot[0]=2,对应源码:++x;所以,可以看出return后面的表达式先执行 iload_0 // 将局部变量表slot[0]的值推入操作数栈顶,也就是说把上面x的值(2)推入栈顶 istore_1 // 弹出栈顶元素(2),保存到局部变量表slot[1],此时slot[1]=2。其实,此时就已经把要return的值准备好了 iconst_3 // 将常量3推入操作数栈顶,这一条指令开始,其实是开始执行finally中的代码了 istore_0 // 弹出栈顶元素(3),保存到局部变量表slot[0],此时slot[0]=3。这两个指令对应源码:x = 3;这里要注意的是,虽然都是更新了x的值,但是finally中的x和try中x的赋值,保存在了不同的局部变量表中 iload_1 // 将局部变量表slot[1]的值推入操作数栈顶,此时栈顶元素的值为2,是第6行指令保存的值,也就是经过++x之后的值 ireturn // 将操作数栈顶的值返回给调用方

Wie aus dem obigen Code ersichtlich ist, lautet die Anweisung nach der Rückkehr Zuerst wird es ausgeführt, dann in der lokalen Variablentabelle gespeichert, dann wird die Anweisung in „finally“ ausgeführt und schließlich wird die Return-Anweisung selbst ausgeführt.

Zusammenfassend lässt sich sagen, dass die Rückgabeanweisung zuletzt ausgeführt wird. Wenn nach der Rückgabe ein Ausdruck vorhanden ist, wird die Anweisung in „finally“ nach der Ausführung des Ausdrucks ausgeführt und die Rückgabeanweisung wird zuletzt ausgeführt. Welche wird also zuerst, schließlich oder return ausgeführt: Wenn nach der Rückgabeanweisung ein Ausdruck oder Methodenaufruf steht, wird dieser zuerst, dann zuletzt und schließlich die Rückgabeanweisung ausgeführt. Genau wie das Ergebnis der obigen Programmdemonstration kann das endgültige Rückgabeergebnis nicht nur anhand der Zuweisung von x beurteilt werden. Auf Befehlsebene werden die beiden Zuweisungen an x ​​an unterschiedlichen Orten in der lokalen Variablentabelle gespeichert.

Schauen wir uns zum Schluss ein Szenario an, das normalerweise nicht so geschrieben wird:

public static int case3() {     int x;     try {         x = 1;         return ++x;     } finally {         x = 3;         return x;     } } # 输出

Dies ist ein Beispiel für die endgültige Rückgabe von Ergebnissen. Es wird nicht empfohlen, es aus der Perspektive des Bytecodes zu analysieren:

iconst_1 // 将常量1推入操作数栈顶 istore_0 // 弹出栈顶元素(1),保存到局部变量表slot[0],此时slot[0]=1。这两条指令对应源码:x = 1; iinc          0, 1 // 对局部变量表slot[0]进行自增(+1)操作,此时slot[0]=2,对应源码:++x;所以,可以看出return后面的表达式先执行 iload_0  // 将局部变量表slot[0]的值推入操作数栈顶,也就是说把上面x的值(2)推入栈顶 istore_1 // 弹出栈顶元素(2),保存到局部变量表slot[1],此时slot[1]=2。 iconst_3 // 将常量3推入操作数栈顶,这一条指令开始,其实是开始执行finally中的代码了 istore_0 // 弹出栈顶元素(3),保存到变量表slot[0],此时slot[0]=3。这两个指令对应源码:x = 3 iload_0  // 将局部变量表slot[0]的值(3)推入操作数栈,这是跟之前不一样的地方,ireturn返回的值选择的局部变量表不一样 ireturn

Das obige ist der detaillierte Inhalt vonWie ist die Ausführungsreihenfolge von Return- und Final-Anweisungen in Java?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen