Java基礎之:OOP——類變數與類方法
類變數與類方法,我們習慣也將其稱為靜態變數與靜態方法。
類變數/靜態變數
通過一個實際案例來了解,為什麼需要使用靜態變數。
引入案例
宣告一個學生類,每建立一個學生物件,統計學生的人數。
public class Test{ public static void main(String[] args){ int count = 0; //區域性變數,累積計數 Student stu1 = new Student("小范"); count ++; Student stu2 = new Student("小黃"); count ++; Student stu3 = new Student("小雨"); count ++; System.out.println("目前學生人數有:" + count); } } class Student{ private String name; public Student(String name){ this.name = name; } }
通過這個案例我們可以看到,count作為一個區域性變數,獨立於Student外,當然也和建立的學生物件沒有任何關聯。以後在訪問count的時候會很麻煩,在Student類中訪問count也很麻煩。
解決案例
package static_args_methods.args; public class Static_args { public static void main(String[] args) { Student student = new Student("小范"); System.out.println(student.showFee()); // 100 Student student2 = new Student("小黃"); System.out.println(student2.showFee()); //200 // System.out.println(Student.fee); //私有屬性,無法訪問 System.out.println(Student.count); //2 } } class Student{ private String name; //static + 訪問修飾符 + 型別 + 屬性名 static private double fee; //學費 static Blackboard bb; //黑板 //訪問修飾符 + static + 型別 + 屬性名 (推薦) public static int count; //人數 public Student(String name) { super(); this.name = name; fee += 100; //每個學生交100學費 count += 1; } public double showFee(){ return fee; } } class Blackboard{ }
案例說明
由此案例,引出類變數/靜態變數的概念及使用。
概念
類變數也叫靜態變數/靜態屬性,是該類的所有物件共享的變數,任何一個該類的物件去訪問它時,取到的都是相同的值,同樣任何一個該類的物件去修改它時,修改的也是同一個變數。
定義語法
訪問修飾符 static 資料型別 變數名; [推薦]
static 訪問修飾符 資料型別 變數名;
訪問方法
類名.類變數名 [推薦]
或者 物件名.類變數名 【靜態變數的訪問修飾符的訪問許可權和範圍 和 普通屬性是一樣的。】
使用說明
-
當需要一個類的所有物件都可以共用一個屬性時,就可以將此屬性設定為靜態屬性。例如,Student中的count屬性。
-
被靜態static修飾過的屬性,在類載入時就會被生成,然後初始化。
-
建議使用“類名.屬性名” 的方式訪問靜態屬性,因為靜態屬性(類變數)的生命週期是隨類的載入開始,隨著類消亡而銷燬。在類載入的時候,並沒有物件被建立,此時也可以使用類變數。
-
類變數是所有物件共享使用的,而普通變數是每個物件都獨有的。
-
類變數的使用,訪問許可權也是由訪問修飾符修飾的。例如:Student 的類變數 count 是 private 修飾的,那麼在 Static_args 類中也不能通過 Student.count 來訪問。
類方法/靜態方法
類方法也叫靜態方法 。
形式如下:
訪問修飾符 static 資料返回型別 方法名() { } 【推薦】
static 訪問修飾符 資料返回型別 方法名() { }
類方法的呼叫:
使用方式: 類名.類方法名 或者 物件名.類方法名 【前提是 滿足訪問修飾符的訪問許可權和範圍】
使用說明
-
類方法與普通方法都是在類載入時就載入了,將其結構資訊放在方法區中。
-
類方法中沒有this關鍵字,也不能使用super關鍵字。因為類方法在類載入時就可以呼叫,此時還沒有物件被生成。而this與super都是代表物件的關鍵字。
-
類方法/靜態方法 只能訪問靜態屬性或者呼叫其他靜態方法,不可以使用成員屬性與成員方法。因為在類方法被載入時,成員屬性與成員方法都還沒有被加載出來,不能使用。【前提是 滿足訪問修飾符的訪問許可權和範圍】
-
而在成員方法(普通方法)中可以使用所有的靜態方法與靜態屬性。【前提是 滿足訪問修飾符的訪問許可權和範圍】
-
但不要誤理解為,靜態方法中使用的任何屬性或方法都必須是靜態的。也可以在靜態方法中宣告普通屬性來使用。
說明案例
public class StaticMethodDetail { public static void main(String[] args) { // TODO Auto-generated method stub //類方法可以通過類名呼叫,也可以通過物件名呼叫 new DD().hi(); DD.hi(); } } class EE { public String name = "EE"; } class DD extends EE { /* * 類方法和普通方法都是隨著類的載入而載入,將結構資訊儲存在方法區 :類方法中無this的引數,普通方法中隱含著this的引數 * 類方法中,不能使用this ,普通方法可以使用this */ private int num = 200; private static String name = "老王"; public static void hi() { //System.out.println(this.num); } //類方法中不允許使用和物件有關的關鍵字,比如this和super public static void ok() { //System.out.println(this.num); //System.out.println(super.name); } //類方法(靜態方法)中 只能訪問 靜態變數 或靜態方法 public void m1() { } public static void hello() { ok(); //m1(); System.out.println(name); } //普通成員方法(非靜態方法),既可以訪問 普通變數(方法),也可以訪問靜態變數(方法) public void m2() { ok(); m1(); System.out.println(name); System.out.println(num); } }
簡單案例
package static_args_methods.methods; public class Static_methods { public static void main(String[] args) { Person person = new Person("小黃", 2000); Person person2 = new Person("小范", 2500); //可以使用類名呼叫,也可以使用物件呼叫 System.out.println(Person.show()); //建議 System.out.println(person2.show()); } } class Person{ private String name; private double salary; //工資 private static double totalSalary; //總工資 public Person(String name, double salary) { super(); this.name = name; this.salary = salary; sumSalary(salary); } //靜態方法 public static void sumSalary(double salary) { totalSalary += salary; } //返回總工資(靜態方法裡只能使用靜態屬性與方法) public static double show() { // salary = 100; //Cannot make a static reference to the non-static field salary // this.totalSalary = 100; //在靜態方法中沒有this指標,也不可以使用super return Person.totalSalary; } }
理解main
由於java虛擬機器需要呼叫類的main()方法,所以該方法的訪問許可權必須是public,又因為java虛擬機器在執行main()方法時不必建立物件,所以該方法必須是static的,該方法接收一個String型別的陣列引數,該陣列中儲存執行java命令時傳遞給所執行的類的引數。
簡單案例
public class TestMain { private String name = "jack"; private static int num = 600; //1.main方法時JVM呼叫,因此 public static //2. String[] args 是執行程式時,可以輸入的 //3. 比如 java TestMain tom jack smith public static void main(String[] args) { for(int i= 0 ; i < args.length;i++) { System.out.println(args[i]); } //m1(); m2(); System.out.println(num); //如果我們就是要再 main呼叫非靜態的成員,需要先建立物件,再呼叫.. TestMain tm = new TestMain(); tm.m1(); } public void m1() { } public static void m2() { } }