單例模式,this,super,final,接口,抽象類以及多態(tài)

單例定義,寫法

單例模式: 在程序運(yùn)行其間,保存類對(duì)象只會(huì)創(chuàng)建一次(確保只有一個(gè)實(shí)例)

實(shí)現(xiàn)步驟:

  1. 私有化構(gòu)造方法

  2. 提供本類的實(shí)例對(duì)象(好多種)

  3. 向類的外部提供一個(gè)方法,獲取類的對(duì)象

為什么使用單例:1.能避免實(shí)例重復(fù)創(chuàng)建 2.應(yīng)用于避免存在多個(gè)實(shí)例引起程序邏輯錯(cuò)誤的場(chǎng)合3.較節(jié)約內(nèi)存

單例寫法案例

  public class Demo{
      public static void main(String[] args) {

          Singleton tv1 = Singleton.getInstance2("張三");
          Singleton tv2 = Singleton.getInstance2("李四");

          System.out.println(tv1 == tv2);//true//比較的是內(nèi)存地址
          tv2.speak();//張三
      }
  }


  class Singleton {
      String name;

      //1.私有化構(gòu)造方法
      private Singleton(String name) {
          this.name = name;
      }

      //2.提供本類的對(duì)象
      private static Singleton singleton1;


          //寫法一:同步懶漢式,3.向外部提供可訪問的方法,并返回當(dāng)前類的對(duì)象
          public synchronized Singleton getInstance1(String name) {
              if (singleton1 == null) {
                  singleton1 = new Singleton(name);
              }
              return singleton1;
          }

      //寫法二:優(yōu)化后的懶漢式,方法一中的同步冗余,3.向外部提供可訪問的方法,并返回當(dāng)前類的對(duì)象
      public static Singleton getInstance2(String name) {
          if (singleton1 == null) {
              synchronized (Singleton.class) {
                  if (singleton1 == null) {
                      singleton1 = new Singleton(name);
                  }
              }
          }
          return singleton1;
      }

      ////////////////////////////////////////////
      //寫法三:餓漢式2.提供本類的對(duì)象
      private static Singleton singleton3 = new Singleton("default");

      //3.向外部提供可訪問的方法,并返回當(dāng)前類的對(duì)象
      public static Singleton getInstance3() {
          return singleton3;
      }

      ////////////////////////////////////////////
      //寫法四:內(nèi)部類

      /**
       * 類級(jí)的內(nèi)部類,也就是靜態(tài)的成員式內(nèi)部類,該內(nèi)部類的實(shí)例與外部類的實(shí)例沒有綁定關(guān)系,
       * 而且只有被調(diào)用到才會(huì)裝載,從而實(shí)現(xiàn)了延遲加載
       *
      private static class SingletonHolder {
          //2.提供本類的對(duì)象
          private static final Singleton instance = new Singleton("default");
      }

      //3.向外部提供可訪問的方法,并返回當(dāng)前類的對(duì)象
      public static Singleton getInstance4() {
          return SingletonHolder.instance;
      }


      ////////////////////////////////////////////
      public void speak() {
          System.out.println(name);
      }

  }

super 、this關(guān)鍵字

方法的重寫:首先存在繼承關(guān)系,然后方法名、參數(shù)、返回?cái)?shù)據(jù)類型都與父類中方法名和參數(shù)相同。父類的私有方法不能被重寫,靜態(tài)只能覆蓋靜態(tài)。

this和super的使用
  • this
    this 代有當(dāng)前類的引用,可以通過this.成員形式來訪問成員變量和方法,可以通過this() 來調(diào)用本類的其它構(gòu)造方法,但必須在第一行
  • super
    super:代表是父類的數(shù)據(jù)空間,并不是一個(gè)引用,因此沒有對(duì)象可以指向可以通過 super.父類成員來訪問父類的成員變量和成員方法;也可以通過super()來調(diào)用父類的構(gòu)造方法,如果父類不存在無參的構(gòu)造方法;在子類中必須調(diào)用super(),來指明初始化父類成員變量的構(gòu)造方法,而且必須在第一行 。

注: super() 和 this()不能同時(shí)出現(xiàn),this和super不能出現(xiàn)靜態(tài)成員方法中

案例

public class Demo {
    public static void main(String[] args){
        Parent parent=new Child(); //多態(tài)
        parent.say("您好");//父類說...您好
                          //子類說...您好

        parent.print(); //父類打印...
    }
}

class Parent {

    public void say(String msg) {
        System.out.println("父類說..." + msg);
    }

    public static void print() {
        System.out.println("父類打印...");
    }

}


class Child extends Parent {

    //重寫父類的方法可以擴(kuò)展功能
    public void say(String msg) {
        super.say(msg); //調(diào)用父類的成員方法

        System.out.println("子類說..." + msg);
    }

    public static void print() { //重寫父類的靜態(tài)方法時(shí),只能以靜態(tài)的方式覆蓋
        //super.print(); //this和super不能出現(xiàn)在靜態(tài)成員方法中
        System.out.println("子類打印...");
    }

}

final關(guān)鍵字

final(C++ const): 最終的,修飾類、成員方法、成員變量、局部變量。
注意:

1、final修飾的類,不能被繼承

2、final修飾的方法,不能被重寫

3、final修飾的成員變量(局部變量),不能被修改

4.String類就是final 修飾的類

final案例

public class Demo {

    public static void main(String[] args) {
        Circle c = new Circle(5);
        System.out.println(String.format("%.2f", c.area()));
    }
}

final class Test1 { //這是一個(gè)最終的類

}

/*
class C_Test extends Test1{ //不能繼承final類

}
*/

class Test2 {

    public final void area() { //final修飾的方法不能被子類重寫

    }
}

class B_Test2 extends Test2 {
    final int a = 10;

    public void area(final int w, final int h) {
        //a=90;//變量不能被修改
        //w=w*h;

        final Test2 t2 = new Test2();

        //final 修飾的引用不能再指向其它對(duì)象
        //t2=new Test2();  //出錯(cuò)
    }
}

//求圓的面積 s=PI*r*r
class Circle {
    public static final double PI = 3.1415;

    private int radius; //半徑


    public Circle(int radius) {
        this.radius = radius;
    }

    public double area() {
        return PI * radius * radius;
    }

}

抽象類 abstract class

abstract: 抽象的,包含抽象方法的類叫抽象類,abstract修飾的類;抽象類也是一個(gè)類,只不過沒有足夠的信息來描述某一事物行為的方法;特點(diǎn):

1、抽象類不能創(chuàng)建對(duì)象,因?yàn)槠渲邪宋磳?shí)現(xiàn)的抽象方法

2、繼承抽象類的子類,如果沒有實(shí)現(xiàn)抽象方法,則這個(gè)類也是抽象類

注意:

抽象類一定是父類,不然沒有存在的意義。

抽象類是有構(gòu)造方法,用于初始化類中的成員變量

  • 抽象類和普通類區(qū)別

相同點(diǎn): 都是類,可以被繼承

不同點(diǎn):抽象類不可以創(chuàng)建對(duì)象,普通類可以創(chuàng)建對(duì)象;抽象類可以包含抽象方法,普通類不能包含抽象方法

另,abstract不能與以下關(guān)鍵字組合使用:

final: final修飾的類不能被繼承,abstract類必須要被繼承(不然沒意義)

static: 靜態(tài)方法可以直接通過類名被調(diào)用,抽象方法不能被調(diào)用

private: 私有方法不能被重寫,抽象方法必須被重寫

案例

public class Demo {

    public static void main(String[] args) {

       //Circle1 c=new Circle1(6); //不能創(chuàng)建抽象類的對(duì)象

        Rectangle r=new Rectangle(8,10);

        System.out.println(r.area());//80.0
    }
}
abstract class Shape{
    public abstract double area();
}

abstract class Circle1 extends Shape{
    public static final double PI=3.14;
    private int radius;

    public Circle1(){}
    public Circle1(int radius){ this.radius=radius;}

    public  abstract double area();
}

class Rectangle extends Shape{
    private int width;
    private int height;

    public Rectangle(int width,int height){
        this.width=width;
        this.height=height;
    }

    public double area(){ //實(shí)現(xiàn)抽象方法
        return width*height;
    }
}

abstract class  Test3{ //注:抽象類中可以不存在抽象方法

}

class C_Test3 extends Test3{

}

interface 接口

  • 定義格式

      interface 接口名{  全局常量; 抽象方法;  }
    
  • 特點(diǎn)
    1、 接口可以實(shí)現(xiàn)多繼承

    2、 接口主要用于被實(shí)現(xiàn),接口中的所有方法,在子類中必須全部實(shí)現(xiàn)

    3、在定義接口實(shí)現(xiàn)類的時(shí),使用implements關(guān)鍵字,而且可以多實(shí)現(xiàn)

  • 擴(kuò)展
    類和類是繼承關(guān)系;類和接口是實(shí)現(xiàn)關(guān)系;通過繼承可以得到繼承體系統(tǒng)中基本功能;通過實(shí)現(xiàn)可以得到除繼承之外的額外功能;注: 一個(gè)可以存在繼承關(guān)系同時(shí)也可以存實(shí)現(xiàn)關(guān)系

案例

  public class Demo{

      public static void main(String[] args) {
          System.out.println(AllAnimalListener.type); //可以通過接口名直接訪問全局變量//動(dòng)物

          //AllAnimalListener all=new AllAnimalListener(); //接口不能創(chuàng)建對(duì)象

          Listener listener = new Animal();
          listener.walk();//動(dòng)物在走...

          AllAnimalListener animalListener = new Animal();
          animalListener.run();//最佳最近調(diào)用原則:多態(tài)性中體現(xiàn)//動(dòng)物在跑...
      }
  }

  interface Listener {
      //聲明全局常量

      void walk();
  }

  interface CatListener {
      void talk();
  }

  //接口的多繼承,因?yàn)樗薪涌谥蟹椒ǘ紱]有實(shí)現(xiàn),不會(huì)存在調(diào)用的不確定性問題
  interface AllAnimalListener extends CatListener, Listener {
      static final String type = "動(dòng)物";

      void run();
  }

  class Animal implements AllAnimalListener, CatListener, Listener { //一個(gè)類可實(shí)現(xiàn)多個(gè)接口

      //必須要實(shí)現(xiàn)或重寫接口的方法 CatListener
      @Override
      public void talk() {
          System.out.println(type + "在說話...");
      }

      //必須要實(shí)現(xiàn)或重寫接口的方法 Listener
      @Override
      public void walk() {
          System.out.println(type + "在走...");
      }

      //必須要實(shí)現(xiàn)或重寫接口的方法 AllAnimalListener
      @Override
      public void run() {
          System.out.println(type + "在跑...");
      }
  }

Java多態(tài)

對(duì)象的多態(tài)性: 多種形態(tài),父類類型的引用指向子類對(duì)象,多態(tài)的前提:存在繼承或?qū)崿F(xiàn)關(guān)系

  class 動(dòng)物{
   public void eat(){}
   }
class 貓 extends 動(dòng)物{
   }
   常態(tài):  貓看成是貓   貓 c=new 貓();
   多態(tài):  貓是動(dòng)物     動(dòng)物 d=new 貓(); //第一種方式體現(xiàn)多態(tài)

   void 方法名(動(dòng)物 d){  //第二種方式體現(xiàn)多態(tài)
    d.eat();
    }
  動(dòng)物 方法名(int type){ //第三種方式體現(xiàn)多態(tài)
  if(type==1){
    return new 貓();
    }
   return new 狗();
   }
  • 多態(tài)的弊端
    只能使用父類中定義的方法,并且子類必須重寫父類中的方法

  • 多態(tài)的好處
    1.有繼承或者實(shí)現(xiàn)接口的關(guān)系

    2.重寫或者實(shí)現(xiàn)父類(接口)的方法

    3.父類指針指向子類對(duì)象

多態(tài)案例

public class Demo {
    public static void main(String[] args) {
        Cat cat = new Cat();//常態(tài)
        cat.eat();//貓吃魚
        cat.catchMouse();//貓抓老鼠

        Animal1 a1 = new Cat(); //多態(tài),第一種方式
        //a1.eat();
        //a1.catchMouse();//出錯(cuò),因?yàn)楦割愔袥]有聲明此方法

        Animal1 a2 = new Dog();//多態(tài)
        //a2.eat();

        eat(a1);//貓吃魚
                //小貓正在吃。。。。
        eat(a2);//狗吃骨頭
                //小狗正在吃。。。。
    }

    public static void eat(Animal1 animal) { //第二種方式體現(xiàn)多態(tài)性
        animal.eat(); //調(diào)用是Animal實(shí)際對(duì)象的方法,實(shí)際對(duì)象可能是Cat、Dog的類對(duì)象

        //通過instanceof關(guān)鍵字判斷對(duì)象是哪一種類型的對(duì)象
        if (animal instanceof Cat) {
            System.out.println("小貓正在吃。。。。");
        } else {
            System.out.println("小狗正在吃。。。。");
        }

    }
}


abstract class Animal1 {
    public abstract void eat(); //虛方法
}

class Cat extends Animal1 {
    public void eat() {
        System.out.println("貓吃魚");
    }

    public void catchMouse() {
        System.out.println("貓抓老鼠");
    }
}

class Dog extends Animal1 {
    public void eat() {
        System.out.println("狗吃骨頭");

    }

    public void kanjia() {
        System.out.println("看家");
    }
}

向上,向下轉(zhuǎn)型

多態(tài)第三種體現(xiàn)方式,向上轉(zhuǎn)型: 子類類型向父類類型轉(zhuǎn)換(自動(dòng)--多態(tài)的體現(xiàn));向下轉(zhuǎn)型: 當(dāng)子類中擴(kuò)展的方法被調(diào)用時(shí),需要將對(duì)象轉(zhuǎn)成子類類型對(duì)象

案例

/**
 * 注意: 為了減少錯(cuò)誤,在強(qiáng)轉(zhuǎn)之前,可以通過instanceof判斷對(duì)象是否為某一種類型
 */
public class Demo{
    public static void main(String[] args) {


        Animal2 a1 = new Cat1(); //向上轉(zhuǎn)換,子類對(duì)象轉(zhuǎn)成父類對(duì)象

        eat(a1);//貓吃魚
        //小貓正在吃。。。。
        // 貓抓老鼠

        Animal2 a2 = newAnimal(Animal2.TYPE_DOG);
        eat(a2);//狗吃骨頭
        //小狗正在吃。。。。
        //看家

    }

    public static void eat(Animal2 animal) { //第二種方式體現(xiàn)多態(tài)性
        animal.eat(); //調(diào)用是Animal實(shí)際對(duì)象的方法,實(shí)際對(duì)象可能是Cat、Dog的類對(duì)象

        //通過instanceof關(guān)鍵字判斷對(duì)象是哪一種類型的對(duì)象
        if (animal instanceof Cat1) {
            System.out.println("小貓正在吃。。。。");


            //需要調(diào)用Cat中擴(kuò)展的方法
            Cat1 c = (Cat1) animal; //向下轉(zhuǎn)型,父類對(duì)象向子類對(duì)象轉(zhuǎn)型
            c.catchMouse();

        } else {
            System.out.println("小狗正在吃。。。。");

            Dog1 d = (Dog1) animal;
            d.kanjia();
        }

    }

    //第三種體現(xiàn)多態(tài)性,根據(jù)類型創(chuàng)建某一動(dòng)物的對(duì)象
    public static Animal2 newAnimal(int type) {
        if (type == Animal2.TYPE_CAT) {
            return new Cat1();
        } else if (type == Animal2.TYPE_DOG) {
            return new Dog1();
        }

        return null;
    }

}

abstract class Animal2 {
    public static final int TYPE_CAT = 1;
    public static final int TYPE_DOG = 2;

    public abstract void eat(); //虛方法
}

class Cat1 extends Animal2 {
    public void eat() {
        System.out.println("貓吃魚");
    }

    public void catchMouse() {
        System.out.println("貓抓老鼠");
    }
}

class Dog1 extends Animal2 {
    public void eat() {
        System.out.println("狗吃骨頭");

    }

    public void kanjia() {
        System.out.println("看家");
    }
}

接口的多態(tài)體現(xiàn)

接口是一種引用數(shù)據(jù)類型,定義接口的引用指向到接口實(shí)現(xiàn)類對(duì)象, 則是接口體現(xiàn)多態(tài)的方式

/**
 * 接口中的多態(tài)
 * 接口與多態(tài)
 *
 */
public class Demo {

    public static void main(String[] args) {
        Listen l1 = new Animal3(); //接口的多態(tài)

        l1.walk();//動(dòng)物在走
        l1.music();//動(dòng)物在唱歌

        Listen l2 = new Person();
        l2.walk();//人在走
        l2.music();// 人在唱歌
    }
}

interface Listen {
    void music();

    void walk();

}

class Animal3 implements Listen {


    @Override
    public void music() {
        System.out.println("動(dòng)物在唱歌");
    }

    @Override
    public void walk() {
        System.out.println("動(dòng)物在走");
    }
}

class Person implements Listen {

    @Override
    public void music() {
        System.out.println("人在唱歌");
    }

    @Override
    public void walk() {
        System.out.println("人在走");
    }
}

多態(tài)中的調(diào)用

  • 多態(tài)中成員特點(diǎn)

    成員變量: 能訪問哪些成員變量,編譯和運(yùn)行時(shí)都看父類

    成員方法: 訪問哪些方法,編譯時(shí)看父類,其運(yùn)行結(jié)果要看子類

    靜態(tài)成員: 都看父類

案例

public class Demo{
    public static void main(String[] args) {
        Parent1 parent1 = new Child1();
        System.out.println("num->" + parent1.num); //成員變量的結(jié)果:在編譯和運(yùn)行都看父類//num->20

        parent1.say();//運(yùn)行哪一個(gè)方法,編譯時(shí)看父類,運(yùn)行時(shí)看子類//Child1 say()

        parent1.fun();//運(yùn)行哪一個(gè)方法:(靜態(tài))編譯和運(yùn)行時(shí)都看父類//Parent1 static fun()


        Child1 child1 = (Child1) parent1;
        System.out.println("num->" + child1.num);//num->50
        child1.say();//Child1 say()
        child1.fun();//Child1 static fun()
    }
}

class Parent1 {
    int num = 20;

    public void say() {
        System.out.println("Parent1 say()");
    }

    public static void fun() {
        System.out.println("Parent1 static fun()");
    }

}

class Child1 extends Parent1 {
    int num = 50;

    public void say() {
        System.out.println("Child1 say()");
    }

    public static void fun() {
        System.out.println("Child1 static fun()");
    }

}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文出自 Eddy Wiki ,轉(zhuǎn)載請(qǐng)注明出處:http://eddy.wiki/interview-java.h...
    eddy_wiki閱讀 1,272評(píng)論 0 5
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,728評(píng)論 18 399
  • (一)Java部分 1、列舉出JAVA中6個(gè)比較常用的包【天威誠信面試題】 【參考答案】 java.lang;ja...
    獨(dú)云閱讀 7,265評(píng)論 0 62
  • 一:java概述:1,JDK:Java Development Kit,java的開發(fā)和運(yùn)行環(huán)境,java的開發(fā)工...
    ZaneInTheSun閱讀 2,813評(píng)論 0 11
  • 《立意》 ——樓蘭 在人間活出珍貴的塵 一定要去大海洗滌一次 跋山涉水的靈魂 溫柔...
    燕返樓蘭閱讀 295評(píng)論 0 4

友情鏈接更多精彩內(nèi)容