我們已經知道類體中的方法分為實例方法和類方法兩種,用static修飾的是類方法。二者有什么區別呢?當一個類創建了一個對象后,這個對象就可以調用該類的方法。
當類的字節碼文件被加載到內存時,類的實例方法不會被分配入口地址,當該類創建對象后,類中的實例方法才分配入口地址,從而實例方法可以被類創建的任何對象調用執行。需要注意的是,當我們創建第一個對象時,類中的實例方法就分配了入口地址,當再創建對象時,不再分配入口地址,也就是說,方法的入口地址被所有的對象共享,當所有的對象都不存在時,方法的入口地址才被取消。
對於類中的類方法,在該類被加載到內存時,就分配了相應的入口地址。從而類方法不僅可以被類創建的任何對象調用執行,也可以直接通過類名調用。類方法的入口地址直到程序退出才被取消。
類方法在類的字節碼加載到內存時就分配了入口地址,因此,Java語言允許通過類名直接調用類方法,而實例方法不能通過類名調用。在講述類的時候我們強調過,在Java語言中,類中的類方法不可以操作實例變量,也不可以調用實例方法,這是因為在類創建對象之前,實例成員變量還沒有分配內存,而且實例方法也沒有入口地址。
java里類變量和實例變量的區別
類體的定義包括成員變量的定義和方法的定義,並且成員變量又分為實例變量和類變量,用static修飾的變量是類變量。那么類變量和實例變量有什么區別呢?
我們已經知道:一個類通過使用new運算符可以創建多個不同的對象,這些對象將被分配不同的內存空間,說得准確些就是:不同的對象的實例變量將被分配不同的內存空間,如果類中的成員變量有類變量,那么所有對象的這個類變量都分配給相同的一處內存,改變其中一個對象的這個類變量會影響其它對象的這個類變量。也就是說對象共享類變量。
我們知道,當Java程序執行時,類的字節碼文件被加載到內存,如果該類沒有創建對象,類的實例成員變量不會被分配內存。但是,類中的類變量,在該類被加載到內存時,就分配了相應的內存空間。如果該類創建對象,那么不同對象的實例變量互不相同,即分配不同的內存空間,而類變量不再重新分配內存,所有的對象共享類變量,即所有的對象的類變量是相同的一處內存空間,類變量的內存空間直到程序退出運行,才釋放所占有的內存。Java語言允許通過類名直接訪問類變量。
package com.j2se;
class 梯形 {
float 上底, 高;
static float 下底; // 類變量。
梯形(float 上底, float 高) {
this.上底 = 上底;
this.高 = 高;
}
float 獲取上底() {
return 上底;
}
float 獲取下底() {
return 下底;
}
}
public class Example4_5 {
public static void main(String args[]) {
梯形 laderOne, laderTwo; // 梯形的字節碼被加載到內存。
梯形.下底 = 60; // 通過類名操作類變量。
laderOne = new 梯形(18.0f, 20);
laderTwo = new 梯形(9.0f, 10);
System.out.println("laderOne的上底:" + laderOne.獲取上底());
System.out.println("laderOne的下底:" + laderOne.獲取下底());
System.out.println("=========");
System.out.println("laderTwo的上底:" + laderTwo.獲取上底());
System.out.println("laderTwo的下底:" + laderTwo.獲取下底());
}
}
laderOne的上底:18.0
laderOne的下底:60.0
=========
laderTwo的上底:9.0
laderTwo的下底:60.0
