instance variable => non-static field(field: data member)
class variable => static field
{
int x1=prt("static Insect.x1 initialized");
int prt(String s)
{
System.out.println(s);
return 47;
}
}
public class Beetle extends Insect
{
public static void main(String[] args)
{
}
}
---------- java ----------
Normal Termination
輸出完成 (耗費 0 秒)。
{
static int x1=prt("static Insect.x1 initialized");
static int prt(String s)
{
System.out.println(s);
return 47;
}
}
public class Beetle extends Insect
{
public static void main(String[] args)
{
}
}
static Insect.x1 initialized
Normal Termination
輸出完成 (耗費 0 秒)。
由於static成員是屬於類別而不是物件,所以當您呼叫static函式時,並不會傳入物件的位置參考,所以static函式中不會有this參考,由於沒有this參考,所以在Java的static函式成員中不允許使用非static成員,因為程式沒有this來參考至物件位址,也就無法辨別要存取哪一個物件的成員,事實上,如果您在static函式中使用非static資料成員,在編譯時就會出現以下的錯誤訊息:
1 |
non-static variable test cannot be referenced from a static context |
或者是在static函式中呼叫非static函式,在編譯時就會出現以下的錯誤訊息:
1 |
non-static method showMe() cannot be referenced from a static context |
如果以c++來說 就是固定一個記憶體位置給宣告成 static 的成員或函式,
不管你 new 幾個物件, static 的成員或函式始終指向同樣的記憶體位置,
所以當你更改 static 的成員的值時
所有 new 出來的物件中的static 的成員的值就都會變了
1. 最常見的就是 main(),宣告為 static 可在任何物件存在之前被呼叫。
2. 在需要建立多個 class 使用的公用 method 時: 如 Math 類別,目的在公用,而不需要擁有自己的狀態,用 public static 會較方便,其它像是: java.lang.System、java.swing.SwingUtilites…等。
3. 建立只在 class 中使用的「外包工作用的 method」: 避免被一些 實體 method 任意存取 實體variable/field。因為 static method 沒有 this,不能擅自呼叫 實體method 或 實體variable。
object 以 member access operator 來 access static member,這和透過 class name 來取得 static member 兩者感覺起來一樣,但語意上不太一樣,至少對 sun 的編譯器來說是不一樣的。前者的寫法會使得 object reference 被 push 進 stack 隨即又 pop 掉,所以會平白犧牲掉一點效率,後者則不會。
Code Convention也不建議這麼寫
都是建議使用ClassName.staticMember
類別包含"資料"和"操作"(或稱方法, 函式).
當產生N個物件時, "資料"被產生N分, 但操作還是只有一份.
因此, "操作"只是被共用來操作N個物件的資料用.
問題是, "一般的操作"只有在物件產生時才可以呼叫,
而"static操作"則在物件產生前就可以呼叫.
(Kalin's 心得)
回歸Beetle...
第二個Beetle印出字串static Insect.x1 initialized, 那是因為執行Beetle時, 雖然在main()裡沒有做任何事, 但是Beetle extends Insect, 而prt()這個method被宣告為static , 所以在執行Beetle時會先跑base class (Insect)的prt()這個mathod.
" base class 建構完成之後,其 instance variable(譯注:亦即資料成員,相對於 class variable)會以其出現次序被初始化 ... "
再次複習一下 :
instance variable => non-static field(field: data member)
class variable => static field
{
int i=9;
int j;
Insect()
{
prt("i="+i+",j="+j);
j=39;
}
static int x1=prt("static Insect.x1 initialized");
static int prt(String s)
{
System.out.println(s);
return 47;
}
}
public class Beetle extends Insect
{
Beetle()
{
System.out.println(prt("j="+j));
}
{
Beetle b = new Beetle();
}
}
static Insect.x1 initialized
i=9,j=0
j=39
47
Normal Termination
輸出完成 (耗費 0 秒)。
{
int i=9;
int j;
Insect()
{
prt("i="+i+",j="+j);
j=39;
}
static int x1=prt("static Insect.x1 initialized");
static int prt(String s)
{
System.out.println(s);
return 47;
}
}
{
int k=prt("Beetle.k initialized");
{
System.out.println(prt("k="+k));
System.out.println(prt("j="+j));
}
{
Beetle b = new Beetle();
prt("Beetle constructor");
}
}
static Insect.x1 initialized
i=9,j=0
Beetle.k initialized
k=47
47
j=39
47
Beetle constructor
Normal Termination
輸出完成 (耗費 0 秒)。

不會拉 教學相長 加油拉