1. 程式人生 > >單例模式 繼承 多型

單例模式 繼承 多型

單例模式有23種,但是她必須滿足 一個類產生一個例項。 單例模式有以下特點: (1)單例模式只有一個例項; (2)單例類必須建立自己的唯一例項; (3)單例類必須給所有其他物件提供這一例項; 懶漢式單例模式:

class MySinglecTon{
    private static  Object lock = new Object();
        private static MySinglecTon singlecTon = null;
        private MySinglecTon(){
            System.out.println("MySinglecTon().init"
); } public static MySinglecTon getSinglecTon() {//提供一個全域性訪問點 if (singlecTon == null) { synchronized (lock) { if (singlecTon == null) { singlecTon = new MySinglecTon(); } } } /*3、if(sigleTon == null) {//第一個執行緒獲取資源後 synchronized (lock) {//接著進行上鎖,如果第一個執行緒的地址沒有賦給第一個執行緒,人後第二個執行緒進來判斷資源為空也可以進來,但是執行不了 sigleTon = new MySigleTon();//至少執行2遍 } }*/
/*2、synchronized (lock) {//第一個執行緒進來之後上鎖, if(sigleTon == null) { //進來獲取資源後,如果將地址沒賦給第一個執行緒,那第二個執行緒無法進入,導致資源的浪費 sigleTon = new MySigleTon(); } }*/ /*1、if(sigleTon == null) {//只適用於單執行緒 sigleTon = new MySigleTon(); }*/ return singlecTon; } public static void main(String[] args)
{ MySinglecTon singlecTon = MySinglecTon.getSinglecTon(); System.out.println(singlecTon); } }

餓漢式單例模式:

class MySingleTon{
    private static MySingleTon singleTon = new MySingleTon();
    private MySingleTon(){
        System.out.println("MySingleTon().init");
    }
    public static MySingleTon getSingleTon(){//提供一個全域性訪問點
        return singleTon;
    }
}
public class eh {
    public static void main(String[] args) {
        MySingleTon singleTon = MySingleTon.getSingleTon();
        System.out.println(singleTon);
    }
}

執行緒安全的單例模式: 執行緒安全 是否有競態條件,就是臨界區程式碼段,有程式碼段之後是否進行了原子性操作,原子性操作就是對其進行加鎖處理。 靜態內部類實現單例模式:

class MysingleTon2{

    private MysingleTon2(){
    }
   
    private static class SingleTon{ //只有訪問靜態內部類的時候才會建立物件
        public static MysingleTon2  a = new MysingleTon2();
    }
    public static MysingleTon2 getInstance(){
       return SingleTon.a;
    }
}
public class Demo3 {
    public static void main(String[] args) {
        MysingleTon2 Singleton2 =  MysingleTon2.getInstance();
        System.out.println(Singleton2 );
    }
}

訪問修飾限定符: (public)基類的資料成員派生類的訪問許可權 在這裡插入圖片描述 繼承: 派生類繼承了基類出建構函式的所有屬性。 super(); 呼叫基類的建構函式 super.data 訪問基類的資料成員 super.fun(); 呼叫基類的成員方法

class Base{
    protected int  cf;
   public Base(int cf){
       System.out.println("Base,init()");
    this.cf = cf;
}
   static {
       System.out.println("Base.static{}");
  }
    {
        System.out.println("Base.instance{}");
    }
}
class Derieve extends Base{
    private int df;
    public Derieve(int cd,int cg){
        super(cd);
        System.out.println("Derieve,init{}");
    }

    static {
        System.out.println("Derieve.static{}");
    }
    {
        System.out.println("Derieve.instance{}");
    }

    public void fun(int cd) {
        System.out.println("Derieve.fun(int)");
    }
}

過載(overload):函式名相同,函式列表不同 與返回值不同,同時在繼承關係上也可以構成過載。 重寫(override):也叫覆蓋 ,函式名相同 引數列表不同,返回值相同, 但在一定條件下可以不同 ,(遵守了協變型別)。

class Base{
    protected int  cf;
   public Base(int cf){
       System.out.println("Base,init()");
    this.cf = cf;
}
   public void fun(){
       System.out.println("Base.fun()");
   }
}
class Derieve extends Base{
    private int df;
    public Derieve(int cd,int cg){
        super(cd);
        System.out.println("Derieve,init{}");
    }

    public void fun(){
        System.out.println("Derieve.fun()");
    }
    public void fun1(int cd) {
        System.out.println("Derieve.fun1(int)");
    }
}

派生類建構函式的初始化順序: 基類派生類靜態塊初始化 =》基類例項塊構造初始化=》派生類例項塊建構函式初始化

基類和派生類的賦值: 只能把派生類的值賦給基類(這也是多型的基礎) 動多型:

class Base{
    protected int cf;
   public Base(int cf){
       System.out.println("Base,init()");
    this.cf = cf;
}
   public void fun(){
       System.out.println("Base.fun()");
   }
   public void fun1(){
       System.out.println("Base.fun1()");
   }
}
class Derieve extends Base{
    private int df;
    public Derieve(int cd,int cg){
        super(cd);
        System.out.println("Derieve,init{}");
    }

    public void fun(){
        System.out.println("Derieve.fun()");
    }
    public void fun1(){
        System.out.println("Derieve.fun1()");
    }
}
public class jc {
    public static void main(String[] args) {
    Base base = new Derieve(111,222);
    base.fun1();//靜多型  編譯的時候
    base.fun();//動多型 執行的時候
    }
}

在這裡插入圖片描述

基類產生的物件存放在堆上的方法表,在其方法區有當前class類的地址,當基類引用了派生類的物件時,其地址會被派生來的地址所覆蓋,從而輸出的為派生類的方法。