Java中的 static 關鍵字,確實是一個關鍵的字(key word),今天就來總結一下它的用法,說說爲何關鍵。java
Java中的 static 關鍵字主要是用來作內存管理的。理解了這句話纔可以比較深刻地理解static。app
static 能夠修飾:函數
凡是被 static 修飾的這四種元素,都屬於class的元素,即類的,而不是類的實例的。ui
1) 靜態變量this
在聲明變量的時候加上 static ,該變量便是靜態變量。spa
這樣作的好處就是內存利用率高,看下下面兩個demo:code
1 // Understanding problem without static variable 2 class Student{ 3 int stuNo; 4 String name; 5 String college="ITS"; 6 }
假設這個"niubility my brother" 的學校有500000000個學生,那麼當每個學生被建立的時候,都會初始化學號、姓名、學校,每一個學生都有本身的學號和姓名,這樣作沒問題;可是每一個學生的college字段都相同,若是每次都聲明一遍的話,是比較耗內存的。這裏的college變量實際上是被該類的全部實例所共享的,所以能夠將它聲明爲 static 的。對象
1 //Program of static variable 2 class Student8{ 3 int rollno; 4 String name; 5 static String college ="ITS"; 6 7 Student8(int r,String n){ 8 rollno = r; 9 name = n; 10 } 11 void display (){System.out.println(rollno+" "+name+" "+college);} 12 13 public static void main(String args[]){ 14 Student8 s1 = new Student8(111,"Karan"); 15 Student8 s2 = new Student8(222,"Aryan"); 16 17 s1.display(); 18 s2.display(); 19 } 20 }
Output:111 Karan ITS
222 Aryan ITS
看下實際內存分配狀況:blog
靜態變量分配在了方法區,堆中該類的全部實例共享方法區中的college。內存
再看一下下面這個栗子:Counter 類中聲明瞭一個count變量,在構造函數中對其進行++操做,由於實例變量在對象被建立的時候分配內存,全部每個對象都有一份本身的count副本,每一個對象對各自count的++操做不會反應到其餘對象上。
1 class Counter{ 2 int count=0;//will get memory when instance is created 3 4 Counter(){ 5 count++; 6 System.out.println(count); 7 } 8 9 public static void main(String args[]){ 10 11 Counter c1=new Counter(); 12 Counter c2=new Counter(); 13 Counter c3=new Counter(); 14 15 } 16 }
Output:1 1 1
由於靜態變量僅僅在類加載的時候分配一次內存,因此若是將count修飾爲static,那麼該類的全部對象將會共享該變量,每個對象對count的操做都會反應到其餘對象上。
1 class Counter2{ 2 static int count=0;//will get memory only once and retain its value 3 4 Counter2(){ 5 count++; 6 System.out.println(count); 7 } 8 9 public static void main(String args[]){ 10 11 Counter2 c1=new Counter2(); 12 Counter2 c2=new Counter2(); 13 Counter2 c3=new Counter2(); 14 15 } 16 }
Output:1 2 3
2)靜態方法
在聲明方法的時候加上 static 關鍵字,即靜態方法:
一個靜態方法的栗子:
1 //Program of changing the common property of all objects(static field). 2 class Student9{ 3 int rollno; 4 String name; 5 static String college = "ITS"; 6 7 static void change(){ 8 college = "BBDIT"; 9 } 10 11 Student9(int r, String n){ 12 rollno = r; 13 name = n; 14 } 15 16 void display (){System.out.println(rollno+" "+name+" "+college);} 17 18 public static void main(String args[]){ 19 Student9.change(); 20 21 Student9 s1 = new Student9 (111,"Karan"); 22 Student9 s2 = new Student9 (222,"Aryan"); 23 Student9 s3 = new Student9 (333,"Sonoo"); 24 25 s1.display(); 26 s2.display(); 27 s3.display(); 28 } 29 }
Output:111 Karan BBDIT 222 Aryan BBDIT 333 Sonoo BBDIT
靜態方法的第二顆栗子:
1 //Program to get cube of a given number by static method 2 class Calculate{ 3 static int cube(int x){ 4 return x*x*x; 5 } 6 7 public static void main(String args[]){ 8 int result=Calculate.cube(5); 9 System.out.println(result); 10 } 11 }
靜態方法的兩個注意點:
1 class A{ 2 int a=40;//non static 3 4 public static void main(String args[]){ 5 System.out.println(a); 6 } 7 }
Output:Compile Time Error
Q)爲何Java的main方法是static的?
Ans)爲了使得在調用main方法以前不須要建立任何實例對象。
3)靜態代碼塊
爲何要有這個東西?幹嗎用呢?
栗子:
1 class A2{ 2 static{System.out.println("static block is invoked");} 3 public static void main(String args[]){ 4 System.out.println("Hello main"); 5 } 6 }
Output:static block is invoked Hello main
Q)沒有main方法的程序能夠執行嗎?
Ans)能夠,在JDK1.7以前執行以下代碼是能夠的:
1 class A3{ 2 static{ 3 System.out.println("static block is invoked"); 4 System.exit(0); 5 } 6 }
Output:static block is invoked (if not JDK7)
可是在JDK1.7會報以下錯誤:
Output:Error: Main method not found in class A3, please define the main method as: public static void main(String[] args)
4)靜態內部類
被static修飾的類,而且處於某個類的內部。
那麼爲何要有靜態內部類呢?看下面的栗子:
1 class TestOuter1{ 2 static int data=30; 3 static class Inner{ 4 void msg(){System.out.println("data is "+data);} 5 } 6 public static void main(String args[]){ 7 TestOuter1.Inner obj=new TestOuter1.Inner(); 8 obj.msg(); 9 } 10 }
Output:data is 30
main方法中建立了一個靜態內部類的實例,而且調用了其msg() 方法。可是這裏並無建立外部類的實例,由於這裏的Inner類是static的,而且能夠訪問外圍類的static成員。若是把Inner以前的static去掉,那麼這裏要這樣寫:
TestStaticInnerClass.Inner obj=new TestStaticInnerClass().new Inner();
須要先建立外一個部類實例,而後才能建立內部類實例。靜態內部類不只高效利用內存,並且使得代碼簡潔。下面是static 內部類編譯後的樣子:
1 // Internal class generated by the compiler 2 import java.io.PrintStream; 3 static class TestOuter1$Inner 4 { 5 TestOuter1$Inner(){} 6 void msg(){ 7 System.out.println((new StringBuilder()).append("data is ") 8 .append(TestOuter1.data).toString()); 9 } 10 }
上例中,若是msg() 方法也是靜態的,那麼內部類的實例也不須要建立了:
1 class TestOuter2{ 2 static int data=30; 3 static class Inner{ 4 static void msg(){System.out.println("data is "+data);} 5 } 6 public static void main(String args[]){ 7 TestOuter2.Inner.msg();//no need to create the instance of static nested class 8 } 9 }
Output:data is 30
以上是關於Java 中 static 關鍵字的理解,參考了:http://www.javatpoint.com/