要研究此問題,我們可以反向工程請參閱「編譯器會做什麼?」 :)
爲此,我們與內容 class C(x: Int){}
運行編譯類C.scala
:
scalac C.scala
此,產生C.class
。 現在,我們可以使用java class disassembler javap來查看編譯器將生成的內容。
運行 javap -p C.class
會產生:
public class C {
public C(int);
}
如果我們用 class D(val x: Int){}
重複整個過程中,我們會產生:
public class D {
private final int x;
public int x();
public D(int);
}
我們可以看到,不同的是,關鍵詞val
告訴類創建一個getter方法。
回到您的假設,如果沒有val
關鍵字,則類變量將被定義爲mutable:這是錯誤的。證明我們可以更深入一級地進行拆解。通過運行:
javap -p -v C.class
我們得到(很多其他的信息中)這個片段:
{
public C(int);
descriptor: (I)V
flags: ACC_PUBLIC
Code:
stack=1, locals=2, args_size=2
0: aload_0
1: invokespecial #14 // Method java/lang/Object."<init>":()V
4: return
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LC;
0 5 1 x I
LineNumberTable:
line 4: 0
line 2: 4
MethodParameters:
Name Flags
x final
}
,你可以清楚地看到,類變量x
仍然宣佈爲final
,因此,不可變。
第一段中的所有3個聲明都是錯誤的:'val'和'var'並不總是公開的,這只是默認值;沒有修飾符,你可能有也可能沒有一個字段(它取決於參數是否用在任何方法中),但它無論如何都是不可變的。 –
我同意他們並不總是公開的;你可以使用'private'修改,但我認爲答案的重點仍然存在,在這種情況下,它們是默認公開的。雖然我可以編輯答案。我願意編輯建議。關於方法,我不確定我完全理解。當你使用像class A(val t:Int)和't'這樣的東西時,這個例子會是類的屬性/字段嗎? –
當你有'class A(i:Int)'時,類'A'沒有'i'的字段。 'i'只是一個(不可變的)構造函數參數。當你有'class A(i:Int){def foo = i}'時,類'A'具有一個私有的不可變字段'i'。 –