5-this、super、final、static、synchronized 關鍵字可以修飾什麼,以及修飾後的作用?

this關鍵字

this關鍵字主要分爲四種情況

  1. 指的是當前對象本身

  2. 當你要把自己作爲參數傳遞給別的對象時,也可以用this

  3. 有時候,我們會用到一些內部類和匿名類,如事件處理

        當在匿名類中用this時,這個this則指的是匿名類或內部類本身。
        這時如果我們要使用外部類的方法和變量的話,則應該加上外部類的類名。
    
  4. 在構造函數中,通過this可以調用同一類中別的構造函數

super關鍵字

有如下Java類:

public class Bird{   
private String name;   
public Bird() { }   
public Bird(String name){ this.name = name; }   
public void walk() { System.out.println(“走路”); }   
public String getName(){ return name; }   
public void setName(String name){ this.name = name; }   
}   

另有一個類Chicken繼承上邊的Bird類;

public class Chicken extends Bird{   
private String crest;   
public Chicken(){ super(); }   
public Chicken(String name,String crest) {   
super(name);   
this.name = name; }   
………….   
}   

在第二個自定義的類Chicken中,super()方法一共出現了兩次,分別是super()和super(name),請問super() 是什麼含義,放在這裏又作何解釋?

1.子類的構造過程中必須調用父類的構造方法。

2.子類可在自己的構造方法中使用super()來調用父類的構造方法。

(1)使用this來調用本類的另外的構造方法。

(2)如果調用super必須寫在子類構造方法的第一行。

3.如果子類的構造方法中沒有顯示的調用父類的構造方法,則系統默認的調用父類的無參的構造方法。

4.如果子類的構造方法中既沒有顯示調用父類的構造方法,而父類中又沒有無參的構造方法,則編譯出錯。

那你這裏第 一個super()無參的就是調用了上面Bird類的Bird() 無參構造方法!

      super(name)這個有參數就是調用public Bird(String name){  this.name = name; }這個構造方法!

super() 是調用父類的構造函數,你例子中有Bird()和Bird(String name)兩個方法,super()是調用Bird()構造函數,而super(name)是調用Birth(String name)構造函數。注意super() 調用的是對應參數個數和類型相同的父類構造函數。 public Chicken(String name,String crest) { super(name); this.name = name; } 應該重複了吧,super(name)應該就是this.name = name。

final關鍵字

  1. final數據
    對於基本數據類型的數據而言,final修飾符表示,該數據不會被修改。
    對於非基本類型的對象引用而言,final修飾符所限定的引用恆定不變。一旦引用被初始化指向一個對象,就無法對其改變以指向另一個對象(然而,對象自身卻是可以被修改的。Java並未提供任何使“對象”恆定不變的途徑。這一限制同樣適用於數組,它也是對象)。
    在這裏插入圖片描述

  2. final方法—不能被重載
    使用final方法的原因有兩個。第一個原因是把方法鎖定,以預防任何繼承類修改它的意義。這是出於設計的考慮:你想要確保在繼承中方法的行爲不變,並且不會被重寫。
    注:類中的private方法隱含爲final方法,它不可被重寫。因此,在private方法前加上final修飾符是沒有意義的。

  3. final類–不能被繼承,final類中的方法默認爲final
    如果某個類整體被定義爲final,則該類不可被繼承,它不可有子類。這種設計可能是出於安全或其他方面的考慮。
    final類中的所有方法都隱含爲final類型的,因爲final類本身是不可被繼承的,所以類中的方法也不能被重寫(override)。在final類中,你可以給方法添加final修飾符,但這不會增加任何意義
    使用final方法的第二個原因是效率。如果你將一個方法指明爲final,就是同意編譯器將針對該方法的所有調用都轉爲內嵌(inline)調用。當編譯器發現一個final方法調用命令時,它會根據自己的謹慎判斷,跳過插入程序代碼的正常方式而執行方法調用機制(將參數壓入棧中,跳至方法代碼處並執行,然後跳回去並清除棧中的參數,處理返回值),並且以方法體中的實際代碼的複本來替代方法調用。這將消除方法調用的開銷。當然,如果一個方法很大,你的程序代碼就會膨脹,你可能看不到內嵌帶來的任何性能提高。因此,你所取得的性能提高會因爲花費於方法內時間總量而被縮減。這意味着Java編譯器能夠觀察到這些情況並明智的抉擇是否對final方法執行內嵌動作。然而,最好是讓編譯器和JVM僅在你明確表示要阻止重寫(override)時,再考慮效率問題,並將方法指明爲final。

    Java中除了static和final方法(private方法屬於final)外,其他所有的方法都是後期綁定(動態綁定)。因此,將方法聲明爲final,可以有效的“關閉”動態綁定,或者是想告訴編譯器,不需要對其進行動態綁定。這樣,編譯器就可以爲final方法調用生成更有效的代碼。然而,大多數情況下,這樣做對程序的整體性能不會產生什麼改觀。

static關鍵字(靜態方法–靜態變量–靜態塊–靜態內部類)

static表示“全局”或者“靜態”的意思,用來修飾成員變量和成員方法,也可以形成靜態static代碼塊,更可以修飾類級內部類,但是Java語言中沒有全局變量的概念。 被static修飾的成員變量和成員方法獨立於該類的任何對象。也就是說,它不依賴類特定的實例,被類的所有實例共享 。只要這個類被加載,Java虛擬機就能根據類名在運行時數據區的方法區內定找到他們 。因此,static對象可以在它的任何對象創建之前訪問,無需引用任何對象。
用public修飾的static成員變量和成員方法本質是全局變量和全局方法,當聲明它類的對象時,不生成static變量的副本,而是類的所有實例共享同一個static變量。 static變量前可以有private修飾,表示這個變量可以在類的靜態代碼塊中,或者類的其他靜態成員方法中使用(當然也可以在非靜態成員方法中使用–廢話),但是不能在其他類中通過類名來直接引用,這一點很重要。實際上你需要搞明白,private是訪問權限限定,static表示不要實例化就可以使用,這樣就容易理解多了。static前面加上其它訪問權限關鍵字的效果也以此類推。

static修飾的成員變量和成員方法習慣上稱爲靜態變量和靜態方法,可以直接通過類名來訪問,訪問語法爲:

類名.靜態方法名(參數列表…)
類名.靜態變量名
用static修飾的代碼塊表示靜態代碼塊,當Java虛擬機(JVM)加載類時,就會執行該代碼塊(用處非常大,呵呵)。
1、static變量
按照是否靜態的對類成員變量進行分類可分兩種:一種是被static修飾的變量,叫靜態變量或類變量;另一種是沒有被static修飾的變量,叫實例變量。兩者的區別是:
對於靜態變量在內存中只有一個拷貝(節省內存),JVM只爲靜態分配一次內存,在加載類的過程中完成靜態變量的內存分配,可用類名直接訪問(方便),當然也可以通過對象來訪問(但是這是不推薦的)。
對於實例變量,沒創建一個實例,就會爲實例變量分配一次內存,實例變量可以在內存中有多個拷貝,互不影響(靈活)。
2、靜態方法
靜態方法可以直接通過類名調用,任何的實例也都可以調用,因此靜態方法中不能用this和super關鍵字,不能直接訪問所屬類的實例變量和實例方法(就是不帶static的成員變量和成員成員方法),只能訪問所屬類的靜態成員變量和成員方法。因爲實例成員與特定的對象關聯!這個需要去理解,想明白其中的道理,不是記憶!!!
因爲static方法獨立於任何實例,因此static方法必須被實現,而不能是抽象的abstract。
3、static代碼塊
static代碼塊也叫靜態代碼塊,是在類中獨立於類成員的static語句塊,可以有多個,位置可以隨便放,它不在任何的方法體內,JVM加載類時會執行這些靜態的代碼塊,如果static代碼塊有多個,JVM將按照它們在類中出現的先後順序依次執行它們,每個代碼塊只會被執行一次。

4、類加載
JVM在第一次使用一個類時,會到classpath所指定的路徑裏去找這個類所對應的字節碼文件,並讀進JVM保存起來,這個過程稱之爲類加載。
可見,無論是變量,方法,還是代碼塊,只要用static修飾,就是在類被加載時就已經"準備好了",也就是可以被使用或者已經被執行。都可以脫離對象而執行。反之,如果沒有static,則必須通過對象來訪問。

注意
聲明爲static的變量實質上就是全局變量。當聲明一個對象時,並不產生static變量的拷貝,而是該類所有的實例變量共用同一個static變量,例如:聲明一個static的變量count作爲new一個類實例的計數。

聲明爲static的方法有以下幾條限制:

它們僅能調用其他的static 方法。
它們只能訪問static數據。
它們不能以任何方式引用this 或super。
static方法與覆蓋
靜態方法只能被隱藏,不能被覆蓋,隱藏表明還存在,還會起作用–子類隱藏父類的靜態方法,仍會執行父類的靜態方法.

synchronized關鍵字

  1. 簡單介紹

synchronized 是java語言關鍵字,當它用來修飾一個方法或者一個代碼塊的時候,能夠保證在同一時刻最多隻有一個線程執行該段代碼。
synchronized 關鍵字,它包括兩種用法:synchronized 方法和 synchronized 塊。

  1. 可以修飾哪些內容

一、 修飾一個代碼塊,被修飾的代碼塊稱爲同步語句塊,其作用的範圍是大括號{}括起來的代碼,作用的對象是調用這個代碼塊的對象;

二、修飾一個方法,被修飾的方法稱爲同步方法,其作用的範圍是整個方法,作用的對象是調用這個方法的對象;

三、修飾一個靜態的方法,其作用的範圍是整個靜態方法,作用的對象是這個類的所有對象;

四、修飾一個類,其作用的範圍是synchronized後面括號括起來的部分,作用的對象是這個類的所有對象。

  1. synchonized(this)和synchonized(object)區別

其實並沒有很大的區別,synchonized(object)本身就包含synchonized(this)這種情況,使用的場景都是對一個代碼塊進行加鎖,效率比直接在方法名上加synchonized高一些(下面分析),唯一的區別就是對象的不同。

對synchronized(this)的一些理解

一、當兩個併發線程訪問同一個對象object中的這個synchronized(this)同步代碼塊時,一個時間內只能有一個線程得到執行。另一個線程必須等待當前線程執行完這個代碼塊以後才能執行該代碼塊。

二、然而,當一個線程訪問object的一個synchronized(this)同步代碼塊時,另一個線程仍然可以訪問該object中的非synchronized(this)同步代碼塊。

三、尤其關鍵的是,當一個線程訪問object的一個synchronized(this)同步代碼塊時,其他線程對object中所有其它synchronized(this)同步代碼塊的訪問將被阻塞。

四、當一個線程訪問object的一個synchronized(this)同步代碼塊時,它就獲得了這個object的對象鎖。結果,其它線程對該object對象所有同步代碼部分的訪問都被暫時阻塞。

4.sychonized method 和 synchonized代碼塊的效率問題

使用前者的對象會獲取該對象中所有synchonized的鎖,也就是其他線程不能訪問所有加了synchonized前綴的方法(不僅僅只是當前運行的方法),影響了其他線程同步方法的訪問,降低了效率。而後者只對當前代碼塊加鎖,其他的同步方法不受影響。

  1. 結論

1.synchronized 方法控制對類成員變量的訪問:每個類實例對應一把鎖,每個 synchronized 方法都必須獲得調用該方法的類實例的鎖方能執行,否則所屬線程阻塞,方法一旦執行,就獨佔該鎖,直到從該方法返回時纔將鎖釋放,此後被阻塞的線程方能獲得該鎖,重新進入可執行狀態。這種機制確保了同一時刻對於每一個類實例,其所有聲明爲 synchronized 的成員函數中至多隻有一個處於可執行狀態(因爲至多隻有一個能夠獲得該類實例對應的鎖),從而有效避免了類成員變量的訪問衝突(只要所有可能訪問類成員變量的方法均被聲明爲 synchronized)。

2.synchronized 塊是這樣一個代碼塊,其中的代碼必須獲得對象 syncObject (如前所述,可以是類實例或類)的鎖方能執行。由於可以針對任意代碼塊,且可任意指定上鎖的對象,故靈活性較高。

3.在static方法前加synchronized:靜態方法屬於類方法,它屬於這個類,獲取到的鎖,是屬於類的鎖。

4.在普通方法前加synchronized:非static方法獲取到的鎖,是屬於當前對象的鎖。

5.類鎖和對象鎖不同,synchronized修飾不加static的方法,鎖是加在單個對象上,不同的對象沒有競爭關係;修飾加了static的方法,鎖是加載類上,這個類所有的對象競爭一把鎖。

參考地址

https://juejin.im/post/5c3c5e0ce51d4551d04511c9
https://blog.csdn.net/wenbingoon/article/details/8887708

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章