我有以下課程:
public class Test {
private int a;
public Test(final int a) {
this.a = a;
}
}
我嘗試使用javac Test.java和不使用final關鍵字 on編譯(使用)a。在這兩種情況下,當我反編譯(使用javap -v -c Test.class)時,我得到以下位元組碼(java 11,打開 jdk):
Classfile /home/sadeep/repos/podium.cubs-cnt-svc-modelruntime/src/main/java/podium/cubs/cnt/svc/modelruntime/Test.class
Last modified Nov 3, 2021; size 261 bytes
MD5 checksum aa55c5cbaad8a25b1ebf28a572fa72e3
Compiled from "Test.java"
public class podium.cubs.cnt.svc.modelruntime.Test
minor version: 0
major version: 55
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #3 // podium/cubs/cnt/svc/modelruntime/Test
super_class: #4 // java/lang/Object
interfaces: 0, fields: 1, methods: 1, attributes: 1
Constant pool:
#1 = Methodref #4.#13 // java/lang/Object."<init>":()V
#2 = Fieldref #3.#14 // podium/cubs/cnt/svc/modelruntime/Test.a:I
#3 = Class #15 // podium/cubs/cnt/svc/modelruntime/Test
#4 = Class #16 // java/lang/Object
#5 = Utf8 a
#6 = Utf8 I
#7 = Utf8 <init>
#8 = Utf8 (I)V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 SourceFile
#12 = Utf8 Test.java
#13 = NameAndType #7:#17 // "<init>":()V
#14 = NameAndType #5:#6 // a:I
#15 = Utf8 podium/cubs/cnt/svc/modelruntime/Test
#16 = Utf8 java/lang/Object
#17 = Utf8 ()V
{
public podium.cubs.cnt.svc.modelruntime.Test(int);
descriptor: (I)V
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: iload_1
6: putfield #2 // Field a:I
9: return
LineNumberTable:
line 6: 0
line 7: 4
line 8: 9
}
SourceFile: "Test.java"
是final關于方法的引數不是一個JVM結構?
編輯:
javap -p -c -v:
Classfile /home/sadeep/Test.class
Last modified Nov 3, 2021; size 228 bytes
MD5 checksum 2f3a79a3c91a62a2d7831651be24168b
Compiled from "test.java"
class Test
minor version: 0
major version: 55
flags: (0x0020) ACC_SUPER
this_class: #3 // Test
super_class: #4 // java/lang/Object
interfaces: 0, fields: 1, methods: 1, attributes: 1
Constant pool:
#1 = Methodref #4.#13 // java/lang/Object."<init>":()V
#2 = Fieldref #3.#14 // Test.a:I
#3 = Class #15 // Test
#4 = Class #16 // java/lang/Object
#5 = Utf8 a
#6 = Utf8 I
#7 = Utf8 <init>
#8 = Utf8 (I)V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 SourceFile
#12 = Utf8 test.java
#13 = NameAndType #7:#17 // "<init>":()V
#14 = NameAndType #5:#6 // a:I
#15 = Utf8 Test
#16 = Utf8 java/lang/Object
#17 = Utf8 ()V
{
private final int a;
descriptor: I
flags: (0x0012) ACC_PRIVATE, ACC_FINAL
public Test(int);
descriptor: (I)V
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: iload_1
6: putfield #2 // Field a:I
9: return
LineNumberTable:
line 3: 0
line 4: 4
line 5: 9
}
SourceFile: "test.java"
看起來即使使用 -p,最終指標也僅為該欄位設定。
uj5u.com熱心網友回復:
TL;DR:你不需要位元組碼中的資訊
final引數上的關鍵字意味著您不能在方法或建構式中為該引數賦值。檢查您是否沒有這樣做是編譯器的作業(如果您這樣做,編譯器將發出錯誤訊息)。一旦編譯器完成了它的作業,我們就可以確信該引數確實始終保持其初始值。不需要在位元組碼中包含宣告引數的資訊final。這就是資訊不存在的原因。
來自 Link182 的評論:
那么我們怎么知道引數在編譯庫中是最終的呢?
你沒有。你不需要。你會用這些資訊做什么?它只與方法的實作者相關。
uj5u.com熱心網友回復:
MethodParameters 屬性用于指示引數是最終的。https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-4.html#jvms-4.7.24
為了讓 javac 添加這個屬性,你需要傳遞-parameters選項。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/346367.html
下一篇:使用php注冊后自動登錄
