關於Java中的static關鍵字

Java中的 static 關鍵字,確實是一個關鍵的字(key word),今天就來總結一下它的用法,說說爲何關鍵。java

Java中的 static 關鍵字主要是用來作內存管理的。理解了這句話纔可以比較深刻地理解static。app

static 能夠修飾:函數

  1. 變量(所謂 class variable)
  2. 方法(所謂 class method)
  3. 代碼塊(所謂 block)
  4. 內部類(所謂 nested class)

凡是被 static 修飾的這四種元素,都屬於class的元素,即類的,而不是類的實例的。ui

 

1) 靜態變量this

在聲明變量的時候加上 static ,該變量便是靜態變量。spa

  • 何時該用 static 來修飾變量呢?該變量被該類的全部實例所共享。
  • 靜態變量在類被加載的時候初始化,且僅分配一次內存。

這樣作的好處就是內存利用率高,看下下面兩個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. 靜態方法不能操做非靜態變量,也不能調用非靜態方法。(這個能夠這樣理解:靜態方法屬於類,直接經過類名就能夠調用,而此時可能沒有任何實例,更談不上操做實例變量和調用實例方法了。)
  2. 靜態方法中不能使用 thissuper 關鍵字。(道理同上)
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)靜態代碼塊

爲何要有這個東西?幹嗎用呢?

  • 用來初始化靜態變量。
  • 在類加載時,在執行main方法以前執行相關操做。

栗子:

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修飾的類,而且處於某個類的內部。

  • 它能夠訪問外部類的靜態成員,包括private成員。
  • 它不能訪問外部類的非靜態成員。(緣由前面說過)

那麼爲何要有靜態內部類呢?看下面的栗子:

 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/

相關文章
相關標籤/搜索