天天看點

[Java 基礎]-- final、static和abstract差別和使用

一、static 修飾屬性、方法和代碼塊

1.static修飾屬性,這個屬性就可以用類名.屬性名來通路,也就是使這個屬性成為本類的類變量,為本類對象所共有。這個屬性就是全類公有。類加載的過程,類本身儲存在檔案中(位元組碼檔案儲存着類的資訊)的,java會通過I/O流把類的檔案(位元組碼檔案)讀入JVM(java虛拟機),這個過程稱為類的加載過程。

JVM(java虛拟機)會通過類路徑(CLASSPATH)來找位元組碼檔案。

類變量,會在加載時自動初始化,初始化規則和執行個體變量相同。

特别:類中的執行個體變量是在建立對象時被初始化的,被static修飾的屬性(類變量),是在類加載時被建立并進行初始化,

   類加載的過程是進行一次。也就是類變量隻會被建立一次。

2.static修飾方法(靜态方法),會使這個方法成為整個類所公有的方法,可以用類名.方法名通路。

"類名.屬性名"以及"類名.方法"通路舉例: 

class Test{

public static String TEST_IP="靜态ip127.0.0.1";

public static void testMethod(){

System.out.println("調用靜态方法成功!");

}

}      

  測試類 

public class Test2{

  public static void main(String args[]){

//1、通過類名.屬性名調用

System.out.println("調用的屬性值:"+Test.TEST_IP);

Test.TEST_IP="新的ip127.0.0.1";//重新修改位址指向的值

System.out.println("調用的屬性值:"+Test.TEST_IP);

//2、調用靜态方法

Test test=new Test();

test.testMethod();

}

}      

特别:

(1)static修飾的方法,不直接能通路本類中的非靜态(static)成員(包括方法和屬性),本類的非靜态方法可以通路本類的靜态成員(包括方法和屬性)靜态方法要慎重使用(原因是靜态變量會一直存在,占用資源),且在靜态方法中不能出現this關鍵字。

(2)父類中是靜态方法,子類中不能覆寫為非靜态方法;在符合覆寫規則的前提下,在父子類中,父類中的靜态方法可以被子類中的靜态

           方法覆寫,但無多态。(在使用對象調用靜态方法時,實則是調用編譯時類型的靜态方法)

(3)父子類中,靜态方法隻能被靜态方法覆寫,父子類中,非靜态方法隻能被非靜态方法覆寫。

   例:java中的main方法必須寫成static的,因為在類加載時無法建立對象,靜态方法可以不通過對象調用是以在類的main方法。

                 所在在類加載時就可以通過main方法入口來運作程式。

3.static修飾初始代碼塊,這時這個初始代碼塊就叫做靜态初始代碼塊,該代碼塊隻在類加載時被執行一次。

可以用靜态初始代碼塊初始化一個類。

   動态初始代碼塊,寫在類體中的“{}”,這個代碼塊是在生成對象的初始化屬性是運作。這種代碼塊叫動态初始代碼塊。

   類在什麼時候會被加載,建立對象時會加載類,調用類中靜态方法或通路靜态屬性也是會加載類的。在加載子類時必會先加載父類,類加            載會有延遲加載原則,隻有在必須加載時才會加載。

二、final修飾變量、方法和類  

1.final修飾變量

變量被final修飾,就會變成常量(常量應大寫),一旦指派不能改變(可以在初始化時直接指派,也可以在構造方法裡也可以指派,

隻能在這兩種方法裡二選一,必須為常量指派);final的常量不會有預設初始值,對于直接在初始化是指派時final修飾符常和static修飾符

一起使用。

2.final修飾方法,被final修飾的方法将不能被其子類覆寫,保持方法的穩定不能被覆寫。

3.final修飾類,被final修飾的類将不能被繼承。final類中的方法也都是final的。

注意一:final,不能用來修飾構造方法,在父類中如果有常量屬性,在子類中使用常量屬性時是不會進行父類的類加載。

          對象一旦建立屬性就不會改變。用final修飾屬性,也用final修飾類(強不變模式),用final修飾屬性(弱不變模式)。

          如:java.lang.String類,不變模式可以實作對象的共享(可以用一個對象執行個體指派給多個對象變量)

          池化的思想,把需要共享的資料放在池中(節省資源空間,共享資料)

注意二:隻有String類可以用“”中的字面值建立對象。在String類中,以字面值建立時,會到Java方法空間的串池空間中去查找,如果有就返      回串池中字元串的位址,并把這個位址付給對象變量。如果沒有則會在串池裡建立一個字元串對象,并傳回其位址付購對象變量,

                      當另一個以字面時,建立對象時則會重複上述過程。

              如果是new在堆空間中建立String類的對象,則不會有上述的過程。

     String類中的intern()方法會将在堆空間中建立的String類對象中的字元串和串池中的比對,如果有相同的串就傳回這個串的串池中

建立和銷毀的資源的開銷是

                     相當大的。這就是推薦大量使用StringBuffer,而不建議使用String的原因!

     String類在字元串連接配接時會先的效率很低,就是因為它所産生的對象的屬性不能被修改的,當連接配接字元串時也就是隻能建立新

                     的對象。造成很多無用的資源開銷和浪費!

三、abstract修飾類和方法

1.abstract修飾類,使這個類成為一個抽象類,類将不能生成對象執行個體,但可以做為對象變量聲明的類型,也就是編譯時類型,抽象類就像當于一類的半成品,需要子類繼承并覆寫其中的抽象方法。

2.abstract修飾方法,使這個方法變成抽象方法,即隻有聲明(定義)而沒有實作,實作部分以";"代替。需要子類繼承實作(覆寫)。

注意:(1)有抽象方法的類一定是抽象類。但是抽象類中不一定都是抽象方法,也可以全是具體方法。

  abstract修飾符在修飾類時必須放在類名前。

          abstract修飾方法就是要求其子類覆寫(實作)這個方法。調用時可以以多态方式調用子類覆寫(實作)後的方法,

即抽象方法必須在其子類中實作,除非子類本身也是抽象類。

         (2)父類是抽象類,其中有抽象方法,那麼子類繼承父類,并把父類中的所有抽象方法都實作(覆寫)了,

子類才有建立對象的執行個體的能 力,否則子類也必須是抽象類。抽象類中可以有構造方法,是子類在構造子類

對象時需要調用的父類(抽象類)的構造方法。

(3)不能放在一起的修飾符:final和abstract,private和abstract,static和abstract,因為abstract修飾的方法是必須在其子類中

實作(覆寫),才能以多态方式調用,以上修飾符在修飾方法時期子類都覆寫不了這個方法,final是不可以覆寫,private是不能

夠繼承到子類,是以也就不能覆寫,static是可以覆寫的,但是在調用時會調用編譯時類型的方法,因為調用的是父類的方法,

而父類的方法又是抽象的方法,又不能夠調用,是以上的修飾符不能放在一起。