java面向?qū)ο?/h1>

八、面向?qū)ο?/h2>

1. 面向?qū)ο蟮娜齻€(gè)階段

  1. 面向?qū)ο蠓治?OOA --> Object Oriented Analysis

    對象:張三,王五,朱六,你,我
    抽取出一個(gè)類----》人類

    類里面有什么:
    動(dòng)詞--》動(dòng)態(tài)特性--》方法
    名詞--》靜態(tài)特性--》屬性

  2. 面向?qū)ο笤O(shè)計(jì) OOD --> Object Oriented Design

    先有類,再有對象:
    類:人類: Person

    對象:zhangsan ,lisi,zhuliu

  3. 面向?qū)ο缶幊?OOP --> Object Oriented Programming

2.創(chuàng)建類和對象

  1. 創(chuàng)建類

    1). 屬性

    ? [修飾符] 屬性類型 屬性名 = [默認(rèn)值] ;

    2).方法

    ? [修飾符] 方法返回值類型 方法名(形參列表) {
    ? // n條語句
    }

    package com.msb;
    /**
     * @Auther: msb-zhaoss
     * 創(chuàng)建類:人類
     */
    public class Person {
        //名詞---》屬性---》成員變量---》放在類中方法外(注意:我們只把有需要的內(nèi)容寫到代碼里,不相關(guān)的東西不要放在代碼中)
        int age ;//年齡
        String name;//姓名
        double height;//身高
        double weight;//體重
        //動(dòng)詞---》方法
        //吃飯
        public void eat(){
            int num = 10;//局部變量:放在方法中
            System.out.println("我喜歡吃飯");
        }
        //睡覺:
        public void sleep(String address){
            System.out.println("我在"+address+"睡覺");
        }
        //自我介紹:
        public String introduce(){
            return "我的名字是:"+name+",我的年齡是:"+age+",我的身高是:"+height+",我的體重是:"+weight;
        }
    }
    
  2. 創(chuàng)建對象

    package com.msb;
    /**
     * @Auther: msb-zhaoss
     */
    public class Test {//測試類
        //這是一個(gè)main方法,是程序的入口:
        public static void main(String[] args) {
            //創(chuàng)建一個(gè)人類的具體的對象/實(shí)例:
            //創(chuàng)建一個(gè)對象,對象的名字叫:zs
            //Person 屬于 引用數(shù)據(jù)類型
            //第一次加載類的時(shí)候,會(huì)進(jìn)行類的加載,初始化創(chuàng)建對象的時(shí)候,對象的屬性沒有給賦值,有默認(rèn)的初始化的值。
            Person zs = new Person();
            zs.name = "張三";
            zs.age = 19;
            zs.height = 180.4;
            zs.weight = 170.4;
            //再創(chuàng)建一個(gè)對象:
            //再次創(chuàng)建類的時(shí)候,就不會(huì)進(jìn)行類的加載了,類的加載只在第一次需要的時(shí)候加載一次
            Person ls = new Person();
            ls.name = "李四";
            ls.age = 18;
            ls.height = 170.6;
            ls.weight = 160.5;
            //對屬性值進(jìn)行讀取:
            System.out.println(zs.name);
            System.out.println(ls.age);
            //對方法進(jìn)行操作:
            //不同的對象,屬性有自己的特有的值,但是方法都是調(diào)用類中通用的方法。
            //屬性:各個(gè)對象的屬性是獨(dú)立的,
            //方法:各個(gè)對象的方法是共享的。
            zs.eat();
            ls.eat();
            zs.sleep("教室");
            /*String str = zs.introduce();
            System.out.println(str);*/
            System.out.println(zs.introduce());
        }
    }
    

3.局部變量和成員變量的區(qū)別

  1. 位置不同

    成員變量:類中方法外定義的變量
    局部變量:方法中定義的變量 代碼塊中定義的變量

  2. 作用范圍不同

    成員變量:當(dāng)前類的很多方法
    局部變量:當(dāng)前一個(gè)方法(當(dāng)前代碼塊

  3. 是否有默認(rèn)值

    成員變量:有
    局部變量:沒有

    局部變量和成員變量.png

引用數(shù)據(jù)類型默認(rèn)值: null

  1. 是否要初始化

    成員變量:不需要,不建議初始化,后續(xù)使用的時(shí)候再賦值即可
    局部變量:一定需要,不然直接使用的時(shí)候報(bào)錯(cuò)

  2. 內(nèi)存中的位置不同

    成員變量:堆內(nèi)存
    局部變量:棧內(nèi)存

  3. 作用時(shí)間不同

    成員變量:當(dāng)前對象從創(chuàng)建到銷毀
    局部變量:當(dāng)前方法從開始執(zhí)行到執(zhí)行完畢

4.構(gòu)造器

  1. 對象創(chuàng)建的過程

    1.第一次遇到Person的時(shí)候,進(jìn)行類的加載(只加載一次)
    2.創(chuàng)建對象,為這個(gè)對象在堆中開辟空間
    3.為對象進(jìn)行屬性的初始化動(dòng)作

  2. 構(gòu)造器定義

    new關(guān)鍵字實(shí)際上是在調(diào)用一個(gè)方法,這個(gè)方法叫構(gòu)造方法(構(gòu)造器)
    調(diào)用構(gòu)造器的時(shí)候,如果你的類中沒有寫構(gòu)造器,那么系統(tǒng)會(huì)默認(rèn)給你分配一個(gè)構(gòu)造器,只是我們看不到罷了。
    可以自己顯式 的將構(gòu)造器編寫出來:
    構(gòu)造器的格式:
    [修飾符] 構(gòu)造器的名字(){
    }

  3. 構(gòu)造器和方法的區(qū)別:

    1.沒有方法的返回值類型
    2.方法體內(nèi)部不能有return語句
    3.構(gòu)造器的名字很特殊,必須跟類名一樣

  4. 構(gòu)造器的作用

    構(gòu)造器的作用:不是為了創(chuàng)建對象,因?yàn)樵谡{(diào)用構(gòu)造器之前,這個(gè)對象就已經(jīng)創(chuàng)建好了,并且屬性有默認(rèn)的初始化的值。
    調(diào)用構(gòu)造器的目的是給屬性進(jìn)行賦值操作的。
    注意:我們一般不會(huì)在空構(gòu)造器中進(jìn)行初始化操作,因?yàn)槟菢拥脑捗總€(gè)對象的屬性就一樣了。
    實(shí)際上,我們只要保證空構(gòu)造器的存在就可以了,里面的東西不用寫

    ==構(gòu)造器相當(dāng)于Python中的__init__方法==

  5. 代碼示例

    package com.msb2;
    /**
     * @Auther: msb-zhaoss
     */
    public class Person {
        //構(gòu)造器:沒有任何參數(shù)的構(gòu)造器我們叫做:空參構(gòu)造器--》空構(gòu)造器
        public Person(){
            /*age = 19;
            name = "lili";
            height = 169.5;*/
        }
        //屬性:
        String name;
        int age;
        double height;
        //方法:
        public void eat(){
            System.out.println("我喜歡吃飯");
        }
    }
    

5.構(gòu)造器重載

  1. 一般保證空構(gòu)造器的存在,空構(gòu)造器中一般不會(huì)進(jìn)行屬性的賦值操作

  2. 一般我們會(huì)重載構(gòu)造器,在重載的構(gòu)造器中進(jìn)行屬性賦值操作

  3. 在重載構(gòu)造器以后,假如空構(gòu)造器忘寫了,系統(tǒng)也不會(huì)給你分配默認(rèn)的空構(gòu)造器了,那么你要調(diào)用的話就會(huì)出錯(cuò)了。

  4. 當(dāng)形參名字和屬性名字重名的時(shí)候,會(huì)出現(xiàn)就近原則:
    在要表示對象的屬性前加上this.來修飾 ,因?yàn)閠his代表的就是你創(chuàng)建的那個(gè)對象

  5. 構(gòu)造器可以寫多個(gè),主要參數(shù)和類型不一樣(和方法一樣的)

  6. ==相當(dāng)于Python中的__init__重載==

  7. 在第一次類加載的時(shí)候會(huì)有個(gè)this關(guān)鍵字, 相當(dāng)于Python中的self,指代對象本身

  8. 在用構(gòu)造器賦值的時(shí)候用this指定變量,否則會(huì)重名,計(jì)算機(jī)會(huì)優(yōu)先使用離自己近的,就會(huì)出現(xiàn)錯(cuò)誤的值

代碼示例一

package com.msb3.msb2;
/**
 * @Auther: msb-zhaoss
 */
public class Person {
    //屬性:
    String name;
    int age;
    double height;
    //空構(gòu)造器
    public Person(){
    }
    public Person(String name,int age,double height){
        //當(dāng)形參名字和屬性名字重名的時(shí)候,會(huì)出現(xiàn)就近原則:
        //在要表示對象的屬性前加上this.來修飾 ,因?yàn)閠his代表的就是你創(chuàng)建的那個(gè)對象
        this.name = name;
        this.age = age;
        this.height = height;
    }
    public Person(String a,int b){
        name = a;
        age = b;
    }
    //方法:
    public void eat(){
        System.out.println("我喜歡吃飯");
    }
}

代碼示例二

package com.msb3.msb2;
/**
 * @Auther: msb-zhaoss
 */
public class Test {
    //這是一個(gè)main方法,是程序的入口:
    public static void main(String[] args) {
        /*
        1.一般保證空構(gòu)造器的存在,空構(gòu)造器中一般不會(huì)進(jìn)行屬性的賦值操作
        2.一般我們會(huì)重載構(gòu)造器,在重載的構(gòu)造器中進(jìn)行屬性賦值操作
        3.在重載構(gòu)造器以后,假如空構(gòu)造器忘寫了,系統(tǒng)也不會(huì)給你分配默認(rèn)的空構(gòu)造器了,那么你要調(diào)用的話就會(huì)出錯(cuò)了。
        4. 當(dāng)形參名字和屬性名字重名的時(shí)候,會(huì)出現(xiàn)就近原則:
        在要表示對象的屬性前加上this.來修飾 ,因?yàn)閠his代表的就是你創(chuàng)建的那個(gè)對象
         */
        Person p = new Person();
        /*p.age = 19;
        p.name = "lili";
        p.height = 180.4;*/
        Person p2 = new Person("lili",19,180.4);
        System.out.println(p2.age);
        System.out.println(p2.height);
        System.out.println(p2.name);
    }
}

6.內(nèi)存分析

  1. 棧: 存放局部變量/形參和開辟方法棧幀
  2. 堆: new出來的對象, 存放全局變量
  3. 方法區(qū): 存放對象的字節(jié)碼信息, 一個(gè)對象存放一個(gè)
  4. 方法和構(gòu)造器運(yùn)行完畢后就會(huì)從內(nèi)存中回收
內(nèi)存分析1.png

7.this

  1. 從上面的效果能夠看到:this指代的就是當(dāng)前對象, 相當(dāng)于Python中的self

  2. this可以修飾屬性

    當(dāng)屬性名字和形參發(fā)生重名的時(shí)候,或者 屬性名字 和局部變量重名的時(shí)候,都會(huì)發(fā)生就近原則,所以如果我要是直接使用變量名字的話就指的是離的近的那個(gè)形參或者局部變量,這時(shí)候如果我想要表示屬性的話,在前面要加上:this.修飾

    如果不發(fā)生重名問題的話,實(shí)際上你要是訪問屬性也可以省略this.

  3. this可以修飾方法

    在同一個(gè)類中,方法可以互相調(diào)用,this.可以省略不寫, 類似于省略self

  4. this可以修飾構(gòu)造器

    同一個(gè)類中的構(gòu)造器可以相互用this調(diào)用,格式為 this(參數(shù))

    ==注意:this修飾構(gòu)造器必須放在第一行==

8. static

? static可以修飾:屬性,方法,代碼塊,內(nèi)部類。

  1. static修飾屬性

    1). 在類加載的時(shí)候一起加載入方法區(qū)中的靜態(tài)域中

    2). 先于對象存在

    3). 訪問方式: 對象名.屬性名 類名.屬性名(推薦)

    4).應(yīng)用場景

    ? 某些特定的數(shù)據(jù)想要在內(nèi)存中共享,只有一塊 --》這個(gè)情況下,就可以用static修飾的屬性

    5).屬性:

    ? 靜態(tài)屬性 (類變量)
    ? 非靜態(tài)屬性(實(shí)例變量)

    6).代碼示例

    package com.msb5;
    /**
     * @Auther: msb-zhaoss
     */
    public class MsbStudent {
        //屬性:
        String name;
        int age;
        static String school;
        //這是一個(gè)main方法,是程序的入口:
        public static void main(String[] args) {
            MsbStudent.school = "馬士兵教育";
            //創(chuàng)建學(xué)生對象:
            MsbStudent s1 = new MsbStudent();
            s1.name = "張三";
            s1.age = 19;
            //s1.school = "馬士兵教育";
            MsbStudent s2 = new MsbStudent();
            s2.name = "李四";
            s2.age = 21;
            //s2.school = "馬士兵教育";
            System.out.println(s2.school);
        }
    }
    
    
    1. static修飾方法
    1. .和修飾屬性一樣, static修飾的方法也是先于對象存在

    2). 在靜態(tài)方法中不能訪問非靜態(tài)的屬性

    3). 再靜態(tài)方法中不能訪問非靜態(tài)的方法

    4).在靜態(tài)方法中不能使用this關(guān)鍵字, 因?yàn)閠his是對象本身,但是靜態(tài)方法又先于對象存在

    5).非靜態(tài)的方法可以用對象名.方法名去調(diào)用

    6).靜態(tài)方法可以用對象名.方法名去調(diào)用, 也可以用類名.方法名調(diào)用(推薦)

    7).在用一個(gè)類中, 方法可以直接調(diào)用

    8).代碼示例

    package com.msb5;
    /**
     * @Auther: msb-zhaoss
     */
    public class Demo {
        int id;
        static int sid;
        public void a(){
            System.out.println(id);
            System.out.println(sid);
            System.out.println("------a");
        }
        //1.static和public都是修飾符,并列的沒有先后順序,先寫誰后寫誰都行
        static public void b(){
            //System.out.println(this.id);//4.在靜態(tài)方法中不能使用this關(guān)鍵字
            //a();//3.在靜態(tài)方法中不能訪問非靜態(tài)的方法
            //System.out.println(id);//2.在靜態(tài)方法中不能訪問非靜態(tài)的屬性
            System.out.println(sid);
            System.out.println("------b");
        }
        //這是一個(gè)main方法,是程序的入口:
        public static void main(String[] args) {
            //5.非靜態(tài)的方法可以用對象名.方法名去調(diào)用
            Demo d = new Demo();
            d.a();
            //6.靜態(tài)的方法可以用   對象名.方法名去調(diào)用  也可以 用  類名.方法名 (推薦)
            Demo.b();
            d.b();
           
        }
    }
    

9.代碼塊

  1. 類的組成

    屬性,方法,構(gòu)造器,代碼塊,內(nèi)部類

  2. 代碼塊的分類(代碼塊就是一個(gè)花括號中的內(nèi)容)

    普通塊,構(gòu)造塊,靜態(tài)塊,同步塊(多線程)

  3. 普通塊

    在方法中的塊, 普通塊限制了局部變量的作用范圍

  4. 構(gòu)造塊

    在類中方法外的塊

  5. 靜態(tài)塊

    在類中方法外的塊,并且被static關(guān)鍵字修飾

  6. ==代碼塊的執(zhí)行順序==

    1). 最先執(zhí)行靜態(tài)塊,只在類加載的時(shí)候執(zhí)行一次,所以一般以后實(shí)戰(zhàn)寫項(xiàng)目:創(chuàng)建工廠,數(shù)據(jù)庫的初始化信息都放入靜態(tài)塊。一般用于執(zhí)行一些全局性的初始化操作。

    2). 再執(zhí)行構(gòu)造塊,(不常用)

    3). 再執(zhí)行構(gòu)造器

    4). 再執(zhí)行方法中的普通塊。

10. 包 import

  1. 包的作用

    為了解決重名問題(實(shí)際上包對應(yīng)的就是盤符上的目錄)

    解決權(quán)限問題

  2. 包名定義

    (1)名字全部小寫
    (2)中間用.隔開
    (3)一般都是公司域名倒著寫 : com.jd com.msb
    (4)加上模塊名字:
    com.jd.login com.jd.register
    (5)不能使用系統(tǒng)中的關(guān)鍵字:nul,con,com1---com9.....
    (6)包聲明的位置一般都在非注釋性代碼的第一行:package com.han;

  3. 導(dǎo)包

    (1)使用不同包下的類要需要導(dǎo)包: import ..; 例如:import java.util.Date;
    (2)在導(dǎo)包以后,還想用其他包下同名的類,就必須要手動(dòng)自己寫所在的包,寫包的全名, 如: int a = jvaa.util.Date()。
    (3)同一個(gè)包下的類想使用不需要導(dǎo)包,可以直接使用。
    (4)在java.lang包下的類,可以直接使用無需導(dǎo)包:

    (5)IDEA中導(dǎo)包快捷鍵:alt+enter
    可以自己設(shè)置自動(dòng)導(dǎo)包

    (6)可以直接導(dǎo)入*:

  4. 在Java中的導(dǎo)包沒有包含和被包含的關(guān)系:設(shè)置目錄平級的格式(不是包含和被包含的顯示)

  5. 靜態(tài)導(dǎo)入

    導(dǎo)入一個(gè)類下所有的靜態(tài)方法需要加static關(guān)鍵字, 否則視為導(dǎo)入類

    package com.msb11;
    //靜態(tài)導(dǎo)入:
    import static java.lang.Math.*;
    //導(dǎo)入:java.lang下的Math類中的所有靜態(tài)的內(nèi)容
    /**
     * @Auther: msb-zhaoss
     */
    public class Test {
        //這是一個(gè)main方法,是程序的入口:
        public static void main(String[] args) {
            System.out.println(random());
            System.out.println(PI);
            System.out.println(round(5.6));
        }
        //在靜態(tài)導(dǎo)入后,同一個(gè)類中有相同的方法的時(shí)候,會(huì)優(yōu)先走自己定義的方法。
        public static int round(double a){
            return 1000;
        }
    }
    

11.面向?qū)ο?-封裝

  1. 概念

    封裝就是把過程和數(shù)據(jù)包圍起來, 對數(shù)據(jù)的訪問只能通過已定義的接口。面向?qū)ο笫加谶@個(gè)基本概念,即現(xiàn)實(shí)世界可以被描繪成一系列完全自制、封裝的對象,對這些對象通過一個(gè)受保護(hù)的接口訪問其他對象。封裝是一種信息隱藏技術(shù),在java中通過關(guān)鍵字private、protected和public實(shí)現(xiàn)封裝。

    什么是封裝?封裝把對象所有組成部分合在一起,封裝定義程序如何引用對象的數(shù)據(jù),封裝實(shí)際上使用方法將類的數(shù)據(jù)隱藏起來,控制用戶對類的修改和訪問數(shù)據(jù)的程度。適當(dāng)?shù)姆庋b可以程序更容易理解和維護(hù),也增強(qiáng)了程序的安全箱

  2. 高內(nèi)聚、低耦合

    高內(nèi)聚:類的內(nèi)部數(shù)據(jù)操作細(xì)節(jié)自己完成,不允許外部干涉;

    低耦合:僅對外暴露少量的方法用于使用。

    隱藏對象內(nèi)部的復(fù)雜性,只對外公開簡單的接口。便于外界調(diào)用,從而提
    高系統(tǒng)的可擴(kuò)展性、可維護(hù)性。通俗的說,把該隱藏的隱藏起來,該暴露
    的暴露出來。這就是封裝性的設(shè)計(jì)思想。

  3. 封裝的好處

    提高代碼的安全性

  4. 以屬性封裝為例:

    (1)將屬性私有化,被private修飾--》加入權(quán)限修飾符,一旦加入了權(quán)限修飾符,其他人就不可以隨意的獲取這個(gè)屬性
    (2)提供public修飾的方法讓別人來訪問/使用
    (3)即使外界可以通過方法來訪問屬性了,但是也不能隨意訪問,因?yàn)樵蹅冊诜椒ㄖ锌梢约尤?限制條件。

  5. 代碼示例一

    public class Girl {//女孩
        //屬性:
        private int age;
        //讀取年齡:
        public int getAge(){
            return age;
        }
        //設(shè)置年齡:
        public void setAge(int age){
            if(age >= 30 ){
                this.age = 18;
            }else{
                this.age = age;
            }
        }
    }
    
    

    代碼示例二: 加入構(gòu)造器

    package com.msb.test2;
    /**
     * @Auther: msb-zhaoss
     */
    public class Student {
        //屬性:
        private int age;
        private String name;
        private String sex;
        //加入對應(yīng)的setter和getter方法:
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getSex() {
            return sex;
        }
        public void setSex(String sex) {
            if("男".equals(sex) || "女".equals(sex) ){//sex是男 或者 是 女
                this.sex = sex;
            }else{
                this.sex = "男";
            }
        }
        //加入構(gòu)造器:
        public Student(){
        }
        public Student(int age,String name,String sex){
            this.age = age;
            this.name = name;
            //this.sex = sex;
            this.setSex(sex);
        }
    }
    
    package com.msb.test2;
    /**
     * @Auther: msb-zhaoss
     */
    public class Test {
        //這是一個(gè)main方法,是程序的入口:
        public static void main(String[] args) {
            //創(chuàng)建一個(gè)Student對象:
            Student s1 = new Student();
            s1.setName("nana");
            s1.setAge(19);
            s1.setSex("女");
            System.out.println(s1.getName()+"---"+s1.getAge()+"----"+s1.getSex());
            Student s2 = new Student(18,"菲菲","asdfasdfsadf");
            System.out.println(s2.getName()+"---"+s2.getAge()+"----"+s2.getSex());
        }
    }
    

12.面向?qū)ο?-繼承

1.定義和用法
  1. 定義

    類是對對象的抽象, 繼承是對類的抽象

    比如學(xué)生類,教師類,員工類,他們都有姓名/年齡/都是人, 就可以抽象出一個(gè)人類

    總結(jié): 繼承就是is - a 的關(guān)系,比如教師是一個(gè)人,學(xué)生是一個(gè)人

  2. 語法

    使用 extends

    public class Student extends Person

    Stedent 繼承自 Person類

  3. 繼承的好處

    1. 提高代碼的復(fù)用性, 父類定義的內(nèi)容,子類可以直接拿過來用就可以了,不用代碼上反復(fù)重復(fù)定義了

      注意:

      父類private修飾的內(nèi)容,子類實(shí)際上也繼承,只是因?yàn)榉庋b的特性阻礙了直接調(diào)用,但是提供了間接調(diào)用的方式,可以間接調(diào)用。

    2. 便于代碼的擴(kuò)展

    3. 為了以后多態(tài)的使用

  4. 一個(gè)父類可以有多個(gè)子類, 但是一個(gè)子類只能有一個(gè)直接父類, 但是可以間接的繼承自其他類

  5. ==繼承具有傳遞性==

    Student -->繼承自 Person -->繼承自O(shè)bject
    Object類是所有類的根基父類。
    所有的類都直接或者間接的繼承自O(shè)bject。

2.權(quán)限修飾符
  1. private: 在當(dāng)前類中可以訪問

  2. default: :缺省修飾符:權(quán)限:到同一個(gè)包下的其他類都可以訪問

  3. protected:權(quán)限:最大到不同包下的子類

  4. public:在整個(gè)項(xiàng)目中都可以訪問

  5. 總結(jié)

    屬性,方法:修飾符:四種:private,缺省,protected,public
    類:修飾符:兩種:缺省,public

    以后寫代碼
    一般屬性:用private修飾 ,方法:用public修飾

  6. 圖示

    權(quán)限修飾符.png
3.方法的重寫
  1. 定義

    發(fā)生在子類和父類中,當(dāng)子類對父類提供的方法不滿意的時(shí)候,要對父類的方法進(jìn)行重寫

  2. 格式要求:

    子類的方法名字和父類必須一致,參數(shù)列表(個(gè)數(shù),類型,順序)也要和父類一致

  3. 重載和重寫的區(qū)別

    重載:在同一個(gè)類中,當(dāng)方法名相同,形參列表不同的時(shí)候 多個(gè)方法構(gòu)成了重載
    重寫:在不同的類中,子類對父類提供的方法不滿意的時(shí)候,要對父類的方法進(jìn)行重寫。

    重載和重寫.png
4.supper關(guān)鍵字
  1. 定義

    super:指的是父類的, super可以修飾屬性,可以修飾方法;

  2. 在子類的方法中,可以通過 super.屬性 super.方法 的方式,顯示的去調(diào)用父類提供的屬性,方法。在通常情況下,super.可以省略不寫:

supper1.png
  1. 需要顯式的使用supper關(guān)鍵字的地方

    在特殊情況下,當(dāng)子類和父類的屬性重名時(shí),你要想使用父類的屬性,必須加上修飾符super.,只能通過super.屬性來調(diào)用
    在特殊情況下,當(dāng)子類和父類的方法重名時(shí),你要想使用父類的方法,必須加上修飾符super.,只能通過super.方法來調(diào)用
    在這種情況下,super.就不可以省略不寫。

    supper2.png
  1. supper修飾構(gòu)造器

    1. supper修飾構(gòu)造器的場景

      其實(shí)我們平時(shí)寫的構(gòu)造器的第一行都有:super() -->作用:調(diào)用父類的空構(gòu)造器,只是我們一般都省略不寫
      所有構(gòu)造器的第一行默認(rèn)情況下都有super(),但是一旦你的構(gòu)造器中顯示的使用super調(diào)用了父類構(gòu)造器,那么這個(gè)super()就不會(huì)給你默認(rèn)分配了。如果構(gòu)造器中沒有顯示的調(diào)用父類構(gòu)造器的話,那么第一行都有super(),可以省略不寫

      supper修飾構(gòu)造器1.png
  1. 如果構(gòu)造器中已經(jīng)顯示的調(diào)用super父類構(gòu)造器,那么它的第一行就沒有默認(rèn)分配的super();了

    supper修飾構(gòu)造器2.png
  1. supper和this修飾構(gòu)造器

    在構(gòu)造器中,super調(diào)用父類構(gòu)造器和this調(diào)用子類構(gòu)造器只能存在一個(gè),兩者不能共存
    因?yàn)閟uper修飾構(gòu)造器要放在第一行,this修飾構(gòu)造器也要放在第一行

    深層原因是因?yàn)樵诶^承中,先調(diào)用supper父類給屬性賦值,在調(diào)用this的話又會(huì)調(diào)用一遍supper, 重復(fù)調(diào)用

    supper修飾構(gòu)造器3.png
  1. IDEA中快捷自動(dòng)生成構(gòu)造器: alt + insert
5.Object類

? 所有類都直接或間接的繼承自O(shè)bject類,Object類是所有Java類的根基類。
? 也就意味著所有的Java對象都擁有Object類的屬性和方法。
? 如果在類的聲明中未使用extends關(guān)鍵字指明其父類,則默認(rèn)繼承Object類。

  1. Object類的toString方法

    1. 作用


      tostring作用.png
    2. 方法原理


      tostring原理.png
    3. 重寫toString()方法

      由于使用toString方法的時(shí)候,打印出來的東西 “不好看”,對于其他人來說不友好,可讀性不好, 所以要重寫

      IDEA快捷鍵 alt + insert

  2. Object類的equals方法

    1. 作用

      equals作用:這個(gè)方法提供了對對象的內(nèi)容是否相等 的一個(gè)比較方式,對象的內(nèi)容指的就是屬性。
      父類Object提供的equals就是在比較==地址,沒有實(shí)際的意義,我們一般不會(huì)直接使用父類提供的方法,
      而是在子類中對這個(gè)方法進(jìn)行重寫。重寫就是比較兩個(gè)對象所有的屬性相等才相等

      equals1.png
equals2.png
  1. instanceof運(yùn)算符/關(guān)鍵字

    語法: a instanceof b

    判斷a對象是否是b這個(gè)類的實(shí)例, 是則返回true,否則返回false

  2. 使用IDEA工具快捷鍵自動(dòng)生成equals方法

    alt + insert

5.類和類的關(guān)系
  1. 如何讓類和類產(chǎn)生關(guān)系

    (1)將一個(gè)類作為另一個(gè)類中的方法的形參
    (2)將一個(gè)類作為另一個(gè)類的屬性

  2. 類和類有多少種關(guān)系

    1. ==繼承關(guān)系==

      繼承指的是一個(gè)類(稱為子類、子接口)繼承另外的一個(gè)類(稱為父類、父接口)的功能,并可以增加它自己的新功能的能力。在Java中繼承關(guān)系通過關(guān)鍵字extends明確標(biāo)識(shí),在設(shè)計(jì)時(shí)一般沒有爭議性。在UML類圖設(shè)計(jì)中,繼承用一條帶空心三角箭頭的實(shí)線表示,從子類指向父類,或者子接口指向父接口。

      繼承關(guān)系.png
  1. ==實(shí)現(xiàn)關(guān)系==

    實(shí)現(xiàn)指的是一個(gè)class類實(shí)現(xiàn)interface接口(可以是多個(gè))的功能,實(shí)現(xiàn)是類與接口之間最常見的關(guān)系。在Java中此類關(guān)系通過關(guān)鍵字implements明確標(biāo)識(shí),在設(shè)計(jì)時(shí)一般沒有爭議性。在UML類圖設(shè)計(jì)中,實(shí)現(xiàn)用一條帶空心三角箭頭的虛線表示,從類指向?qū)崿F(xiàn)的接口。

    實(shí)現(xiàn)關(guān)系.png
  1. ==依賴關(guān)系==

    簡單的理解,依賴就是一個(gè)類A使用到了另一個(gè)類B,而這種使用關(guān)系是具有偶然性的、臨時(shí)性的、非常弱的,但是類B的變化會(huì)影響到類A。比如某人要過河,需要借用一條船,此時(shí)人與船之間的關(guān)系就是依賴。表現(xiàn)在代碼層面,讓類B作為參數(shù)被類A在某個(gè)method方法中使用。在UML類圖設(shè)計(jì)中,依賴關(guān)系用由類A指向類B的帶箭頭虛線表示。

    依賴關(guān)系.png
  1. ==關(guān)聯(lián)關(guān)系==

    關(guān)聯(lián)體現(xiàn)的是兩個(gè)類之間語義級別的一種強(qiáng)依賴關(guān)系,比如我和我的朋友,這種關(guān)系比依賴更強(qiáng)、不存在依賴關(guān)系的偶然性、關(guān)系也不是臨時(shí)性的,一般是長期性的,而且雙方的關(guān)系一般是平等的。關(guān)聯(lián)可以是單向、雙向的。表現(xiàn)在代碼層面,為被關(guān)聯(lián)類B以類的屬性形式出現(xiàn)在關(guān)聯(lián)類A中,也可能是關(guān)聯(lián)類A引用了一個(gè)類型為被關(guān)聯(lián)類B的全局變量。在UML類圖設(shè)計(jì)中,關(guān)聯(lián)關(guān)系用由關(guān)聯(lián)類A指向被關(guān)聯(lián)類B的帶箭頭實(shí)線表示,在關(guān)聯(lián)的兩端可以標(biāo)注關(guān)聯(lián)雙方的角色和多重性標(biāo)記。

    關(guān)聯(lián)關(guān)系.png
  1. ==聚合關(guān)系==

    聚合是關(guān)聯(lián)關(guān)系的一種特例,它體現(xiàn)的是整體與部分的關(guān)系,即has-a的關(guān)系。此時(shí)整體與部分之間是可分離的,它們可以具有各自的生命周期,部分可以屬于多個(gè)整體對象,也可以為多個(gè)整體對象共享。比如計(jì)算機(jī)與CPU、公司與員工的關(guān)系等,比如一個(gè)航母編隊(duì)包括海空母艦、驅(qū)護(hù)艦艇、艦載飛機(jī)及核動(dòng)力攻擊潛艇等。表現(xiàn)在代碼層面,和關(guān)聯(lián)關(guān)系是一致的,只能從語義級別來區(qū)分。在UML類圖設(shè)計(jì)中,聚合關(guān)系以空心菱形加實(shí)線箭頭表示。

    聚合關(guān)系.png
  1. ==組合關(guān)系==

    組合也是關(guān)聯(lián)關(guān)系的一種特例,它體現(xiàn)的是一種contains-a的關(guān)系,這種關(guān)系比聚合更強(qiáng),也稱為強(qiáng)聚合。它同樣體現(xiàn)整體與部分間的關(guān)系,但此時(shí)整體與部分是不可分的,整體的生命周期結(jié)束也就意味著部分的生命周期結(jié)束,比如人和人的大腦。表現(xiàn)在代碼層面,和關(guān)聯(lián)關(guān)系是一致的,只能從語義級別來區(qū)分。在UML類圖設(shè)計(jì)中,組合關(guān)系以實(shí)心菱形加實(shí)線箭頭表示。

    組合關(guān)系.png
  1. ==總結(jié)==

14.面向?qū)ο?-多態(tài)

1. 定義
  1. 多態(tài)跟屬性無關(guān),多態(tài)指的是方法的多態(tài),而不是屬性的多態(tài)。

  2. 先有父類,再有子類:-->繼承 先有子類,再抽取父類 ---->泛化

  3. 什么是多態(tài)

    多態(tài)就是多種狀態(tài):同一個(gè)行為,不同的子類表現(xiàn)出來不同的形態(tài)。
    多態(tài)指的就是同一個(gè)方法調(diào)用,然后由于對象不同會(huì)產(chǎn)生不同的行為。

  4. 多態(tài)的好處

    為了提高代碼的擴(kuò)展性,符合面向?qū)ο蟮脑O(shè)計(jì)原則:開閉原則。
    開閉原則:指的就是擴(kuò)展是 開放的,修改是關(guān)閉的。
    注意:多態(tài)可以提高擴(kuò)展性,但是擴(kuò)展性沒有達(dá)到最好,以后我們會(huì)學(xué)習(xí) 反射

  5. ==多態(tài)的要素==

    1). 繼承: Cat extends Animal ,Pig extends Animal, Dog extends Animal
    2). 重寫:子類對父類的方法shout()重寫
    3). 父類引用指向子類對象:

    Pig p = new Pig();
    Animal an = p;
    //合成一句就是
    Animal an = new Pig();
    

    示例二

    public void play(Animal an){//Animal an = an = new Pig();
            an.shout();
        }
    Animal an = new Pig();
    g.play(an); //
    

    上面的代碼,也是多態(tài)的一種非常常見的應(yīng)用場合:父類當(dāng)方法的形參,然后傳入的是具體的子類的對象,
    然后調(diào)用同一個(gè)方法,根據(jù)傳入的子類的不同展現(xiàn)出來的效果也不同,構(gòu)成了多態(tài)

    ===左側(cè):編譯期的類型 Animal類型
    =右側(cè):運(yùn)行期的類型 Pig類型==

  6. 多態(tài)代碼示例

    1).父類-->動(dòng)物類

    public class Animal {//父類:動(dòng)物:
        public void shout(){
            System.out.println("我是小動(dòng)物,我可以叫。。。");
        }
    }
    

    2).子類-->小狗類

    public class Dog extends Animal{
        //喊叫:
        public void shout(){
            System.out.println("我是小狗,我可以汪汪叫");
        }
        public void guard(){
            System.out.println("我是小狗,我可以看家護(hù)院,保護(hù)我的小主人。。。");
        }
    }
    

    3).子類-->小貓類

    public class Cat extends Animal{
        //喊叫方法:
        public void shout(){
            System.out.println("我是小貓,可以喵喵叫");
        }
        public void scratch(){
            System.out.println("我是小貓,我可以撓人");
        }
    }
    

    4). 女孩類

    public class Girl {
        //跟貓玩耍:
        /*public void play(Cat cat){
            cat.shout();
        }*/
        //跟狗玩耍:
        /*public void play(Dog dog){
            dog.shout();
        }*/
        //跟小動(dòng)物玩耍:
        public void play(Animal an){
            an.shout();
        }
    }
    

    5). 程序入口

    public class Test {
        //這是一個(gè)main方法,是程序的入口:
        public static void main(String[] args) {
            //具體的貓:--》貓的對象
            //Cat c = new Cat();
            //具體的小女孩:--》女孩的對象
            Girl g = new Girl();
            //小女孩跟貓玩:
            //g.play(c);
            //具體的狗---》狗的對象:
            //Dog d = new Dog();
            //小女孩跟狗玩:
            //g.play(d);
            //具體的動(dòng)物:--》動(dòng)物的對象:
            //Cat c = new Cat();
            //Dog d = new Dog();
            Pig p = new Pig();
            Animal an = p;
            g.play(an);
        }
    }
    
2.向上/向下轉(zhuǎn)型
  1. 在多態(tài)中, 父類類型不能直接訪問子類獨(dú)有的屬性和方法, 如果想要訪問, 就要轉(zhuǎn)型

  2. 父類往子類轉(zhuǎn)叫做向下轉(zhuǎn)型, 子類往父類轉(zhuǎn)叫做向上轉(zhuǎn)型

  3. 示例

    轉(zhuǎn)型1.png
轉(zhuǎn)型2.png

現(xiàn)在我就想訪問到eat()方法和weight屬性:

public class Demo {
    //這是一個(gè)main方法,是程序的入口:
    public static void main(String[] args) {
        Pig p = new Pig();
        Animal an = p;//轉(zhuǎn)型:向上轉(zhuǎn)型
        an.shout();
        //加入轉(zhuǎn)型的代碼:
        //將Animal轉(zhuǎn)為Pig類型:
        Pig pig = (Pig)an ;//轉(zhuǎn)型:向下轉(zhuǎn)型
        pig.eat();
        pig.age = 10;
        pig.weight = 60.8;
    }
}

對應(yīng)內(nèi)存

轉(zhuǎn)型3.png

==之前的equals方法中也涉及到轉(zhuǎn)型==

equals轉(zhuǎn)型.png
3.簡單工廠模式
  1. 簡述

    不僅可以使用父類做方法的形參,還可以使用父類做方法的返回值類型,真實(shí)返回的對象可以是該類的任意一個(gè)子類對象

    簡單工廠模式的實(shí)現(xiàn),它是解決大量對象創(chuàng)建問題的一個(gè)解決方案。將創(chuàng)建和使用分開,工廠負(fù)責(zé)創(chuàng)建,使用者直接調(diào)用即可。

  2. 簡單工廠模式的基本要求

    1). 定義一個(gè)static方法,通過類名直接調(diào)用

    2). 返回值類型是父類類型,返回的可以是其任意子類類型

    3). 傳入一個(gè)字符串類型的參數(shù),工廠根據(jù)參數(shù)創(chuàng)建對應(yīng)的子類產(chǎn)品

  3. 代碼示例

    public class Test {
        public static void main(String[] args) {
            Girl g = new Girl();
            //Cat c = new Cat();
            //Dog d = new Dog();
            //Pig p = new Pig();
            Animal an = PetStore.getAnimal("狗");
            g.play(an);
        }
    }
    
    public class PetStore {//寵物店 ---》工廠類
        //方法:提供動(dòng)物
        public static Animal getAnimal(String petName){//多態(tài)的應(yīng)用場合(二)
            Animal an = null;
            if("貓".equals(petName)){//petName.equals("貓") --》這樣寫容易發(fā)生空指針異常
                an = new Cat();
            }
            if("狗".equals(petName)){
                an = new Dog();
            }
            if("豬".equals(petName)){
                an = new Pig();
            }
            return an;
        }
    }
    

14. final關(guān)鍵字

1.final修飾變量
  • final修飾一個(gè)基本數(shù)據(jù)類型的變量,變量的值不可以改變,這個(gè)變量也變成了一個(gè)字符常量,約定俗稱的規(guī)定:名字大寫

  • final修飾引用數(shù)據(jù)類型,那么地址值就不可以改變

    final Dog d = new Dog();//final修飾引用數(shù)據(jù)類型,那么地址值就不可以改變
    //d = new Dog(); -->地址值不可以更改
    //d對象的屬性依然可以改變:
    d.age = 10;
    d.weight = 13.7;
    
  • final修飾引用數(shù)據(jù)類型后, 在方法中可以重新賦值

    final Dog d2 = new Dog();
    a(d2);
    public static void a(Dog d){
        d = new Dog();  //可以重新賦值
    }
    
  • final修飾形參, 對象不可以重新賦值

    final Dog d2 = new Dog();
    a(d2);
        public static void b(final Dog d){//d被final修飾 ,指向不可以改變
            d = new Dog();
        }
    
2.final修飾方法
  • final修飾方法,那么這個(gè)方法不可以被該類的子類重寫
3.final修飾類
  • final修飾類,代表沒有子類,該類不可以被繼承
  • 一旦一個(gè)類被final修飾,那么里面的方法也沒有必要用final修飾了(final可以省略不寫)
5.案例: JDK提供的Math類
  1. 使用Math類的時(shí)候無需導(dǎo)包,直接使用即可
  2. 因?yàn)楸籪inal修飾, Math類沒有子類,不能被其他類繼承了
  3. 里面的屬性全部被final修飾,方法也是被final修飾的,只是省略不寫了
    原因:子類沒有必要進(jìn)行重寫。
  4. ==Math構(gòu)造器被 private修飾符修飾, 所以Math不能被示例化, 不能創(chuàng)建對象==
  5. ==Math所有的屬性和方法都被static修飾符修飾, 只能通過 類名.方法名/類名.屬性名 去調(diào)用==

15.抽象類/抽象方法/abstract關(guān)鍵字

  1. 定義

    使用abstract關(guān)鍵字修飾的類和方法稱為抽象類, 抽象方法需要將方法體去掉,如:

    public abstract void sleep();
    
  2. 特點(diǎn):

    1. 如果一個(gè)類中有方法是抽象方法, 那么這個(gè)類也要變成一個(gè)抽象類
    2. 一個(gè)抽象類中可以有0-n個(gè)抽象方法
    3. 抽象類可以被其他類繼承
    4. 如果一個(gè)類繼承自抽象類, 那么他的子類要么也變成抽象類, 要實(shí)現(xiàn)抽閑類的所有抽象方法, 一般是重寫抽象方法
    5. 抽象類不可以創(chuàng)建對象
    6. 抽象類的子類可以創(chuàng)建對象
  3. 抽象類的作用

    在抽象類中定義抽象方法,目的是為了為子類提供一個(gè)通用的模板,

    子類可以在模板的基礎(chǔ)上進(jìn)行開發(fā),先重寫父類的抽象方法,然后可以擴(kuò)展子類自己的內(nèi)容。

    抽象類設(shè)計(jì)避免了子類設(shè)計(jì)的隨意性,通過抽象類,子類的設(shè)計(jì)變得更加嚴(yán)格,進(jìn)行某些程度上的限制。

  4. ==面試題==

    1. 抽象類不能創(chuàng)建對象,那么抽象類中是否有構(gòu)造器?

      抽象類中一定有構(gòu)造器。構(gòu)造器的作用 給子類初始化對象的時(shí)候要先super調(diào)用父類的構(gòu)造器。

    2. 抽象類是否可以被final修飾?

      不能被final修飾,因?yàn)槌橄箢愒O(shè)計(jì)的初衷就是給子類繼承用的。要是被final修飾了這個(gè)抽象類了,就不存在繼承了,就沒有子類。

  5. 代碼示例

    package com.msb.test03;
    //4.一個(gè)類中如果有方法是抽象方法,那么這個(gè)類也要變成一個(gè)抽象類。
    //5.一個(gè)抽象類中可以有0-n個(gè)抽象方法
    public abstract class Person {
        //1.在一個(gè)類中,會(huì)有一類方法,子類對這個(gè)方法非常滿意,無需重寫,直接使用
        public void eat(){
            System.out.println("一頓不吃餓得慌");
        }
        //2.在一個(gè)類中,會(huì)有一類方法,子類對這個(gè)方法永遠(yuǎn)不滿意,會(huì)對這個(gè)方法進(jìn)行重寫。
        //3.一個(gè)方法的方法體去掉,然后被abstract修飾,那么這個(gè)方法就變成了一個(gè)抽象方法
        public abstract void say();
        public abstract void sleep();
    }
    //6.抽象類可以被其他類繼承:
    //7.一個(gè)類繼承一個(gè)抽象類,那么這個(gè)類可以變成抽象類
    //8.一般子類不會(huì)加abstract修飾,一般會(huì)讓子類重寫父類中的抽象方法
    //9.子類繼承抽象類,就必須重寫全部的抽象方法
    //10.子類如果沒有重寫父類全部的抽象方法,那么子類也可以變成一個(gè)抽象類。
    class Student extends Person{
        @Override
        public void say() {
            System.out.println("我是東北人,我喜歡說東北話。。");
        }
        @Override
        public void sleep() {
            System.out.println("東北人喜歡睡炕。。");
        }
    }
    class Demo{
        //這是一個(gè)main方法,是程序的入口:
        public static void main(String[] args) {
            //11.創(chuàng)建抽象類的對象:-->抽象類不可以創(chuàng)建對象
            //Person p = new Person();
            //12.創(chuàng)建子類對象:
            Student s = new Student();
            s.sleep();
            s.say();
            
            //13.多態(tài)的寫法:父類引用只想子類對象:
            Person p  = new Student();
            p.say();
            p.sleep();
        }
    }
    

16.接口

1. JDK1.8之前的接口
  1. 接口聲明格式

    [訪問修飾符] interface 接口名 [extends 父接口1,父接口2…] {

    }

  2. 接口的特點(diǎn)

    1. 類是類, 接口是接口, 他們是同一層次的概念

    2. 接口中沒有構(gòu)造器

    3. 接口聲明關(guān)鍵字: interface

    4. 在JDK1.8之前, 接口中只有兩部分

      • 常量: 有固定的修飾符 public static final

        public static final int NUM = 10;
        
      • 抽象方法:固定修飾符:public abstract

        public abstract void a();
        
      • ==注意:修飾符可以省略不寫,IDE會(huì)幫你自動(dòng)補(bǔ)全,但是初學(xué)者建議寫上,防止遺忘。==

    5. 類和接口是什么關(guān)系?

      實(shí)現(xiàn)關(guān)系, 類實(shí)現(xiàn)接口

    6. 一旦實(shí)現(xiàn)一個(gè)接口, 那么實(shí)現(xiàn)類要重寫接口中的全部抽象方法

    7. 如果沒有全部重寫抽象方法, 那么這個(gè)類可以變成一個(gè)抽象類

    8. ==java只有單繼承, 但是可以多實(shí)現(xiàn)==

      一個(gè)類只有一個(gè)父類, 但是實(shí)現(xiàn)類實(shí)現(xiàn)接口的話, 可以實(shí)現(xiàn)多個(gè)接口

      這是因?yàn)槿绻麅蓚€(gè)父類中都有相同的方法的話會(huì)產(chǎn)生沖突, 接口沒有方法體, 都是要重寫的, 所以不存在這個(gè)問題

    9. 可以同時(shí)有繼承和接口, 順序?yàn)橄壤^承, 再實(shí)現(xiàn)

      示例: extends Person implements TestInterface01,TestInterface02

  3. 接口的作用

    1. 定義規(guī)則,只是跟抽象類不同地方在哪?它是接口不是類。
    2. 接口定義好規(guī)則之后,實(shí)現(xiàn)類負(fù)責(zé)實(shí)現(xiàn)即可。
  4. ==繼承和實(shí)現(xiàn)==

    繼承: 子類對父類的實(shí)現(xiàn)

    實(shí)現(xiàn): 實(shí)現(xiàn)類對接口的實(shí)現(xiàn)

    示例:

    繼承:手機(jī) extends 照相機(jī) “is-a”的關(guān)系,手機(jī)是一個(gè)照相機(jī), 這種寫法不合適

    實(shí)現(xiàn): 手機(jī) implements 拍照功能 “has-a”的關(guān)系,手機(jī)具備照相的能力, 這種比較好

  5. 多態(tài)的應(yīng)用場合

    1. 父類當(dāng)作方法的形參, 傳入具體的子類對象
    2. 父類當(dāng)作方法的返回值, 返回的是具體的子類對象
    3. 接口當(dāng)作方法的形參, 傳入具體的實(shí)現(xiàn)類對象
    4. 接口當(dāng)作方法的返回值, 返回的是具體的實(shí)現(xiàn)類的對象
  6. 接口不能創(chuàng)建對象, 但是可以創(chuàng)建實(shí)現(xiàn)類的對象

  7. 接口中常量的訪問

    1. 接口.常量
    2. 實(shí)現(xiàn)類.常量
    3. 實(shí)現(xiàn)類對象.常量
  8. 接口和抽象類的區(qū)別

    接口1.png
接口2.png
  1. 代碼示例

    package com.msb.test04;
    /**
     * 1.類是類,接口是接口,它們是同一層次的概念。
     * 2.接口中沒有構(gòu)造器
     * 3.接口如何聲明:interface
     * 4.在JDK1.8之前,接口中只有兩部分內(nèi)容:
     * (1)常量:固定修飾符:public static final
     * (2)抽象方法:固定修飾符:public abstract
     * 注意:修飾符可以省略不寫,IDE會(huì)幫你自動(dòng)補(bǔ)全,但是初學(xué)者建議寫上,防止遺忘。
     */
    public interface TestInterface01 {
        //常量:
        /*public static final*/ int NUM = 10;
        //抽象方法:
        /*public abstract*/ void a();
        /*public abstract*/ void b(int num);
        /*public abstract*/ int c(String name);
    }
    interface TestInterface02{
        void e();
        void f();
    }
    /*
    5.類和接口的關(guān)系是什么? 實(shí)現(xiàn)關(guān)系  類實(shí)現(xiàn)接口:
    6.一旦實(shí)現(xiàn)一個(gè)接口,那么實(shí)現(xiàn)類要重寫接口中的全部的抽象方法:
    7.如果沒有全部重寫抽象方法,那么這個(gè)類可以變成一個(gè)抽象類。
    8.java只有單繼承,java還有多實(shí)現(xiàn)
    一個(gè)類繼承其他類,只能直接繼承一個(gè)父類
    但是實(shí)現(xiàn)類實(shí)現(xiàn)接口的話,可以實(shí)現(xiàn)多個(gè)接口
    9.寫法:先繼承 再實(shí)現(xiàn):extends Person implements TestInterface01,TestInterface02
     */
    class Student extends Person implements TestInterface01,TestInterface02 {
        @Override
        public void a() {
            System.out.println("---1");
        }
        @Override
        public void b(int num) {
            System.out.println("---2");
        }
        @Override
        public int c(String name) {
            return 100;
        }
        @Override
        public void e() {
            System.out.println("---3");
        }
        @Override
        public void f() {
            System.out.println("---4");
        }
    }
    class Test{
        //這是一個(gè)main方法,是程序的入口:
        public static void main(String[] args) {
            //10.接口不能創(chuàng)建對象:
            //TestInterface02 t = new TestInterface02();
            TestInterface02 t = new Student();//接口指向?qū)崿F(xiàn)類 ---》多態(tài)
            //11.接口中常量如何訪問:
            System.out.println(TestInterface01.NUM);
            System.out.println(Student.NUM);
            Student s = new Student();
            System.out.println(s.NUM);
            TestInterface01 t2 = new Student();
            System.out.println(t2.NUM);
        }
    }
    
2.JDK1.8之后
  1. 新增兩個(gè)非抽象方法

    1. 被public default修飾的非抽象方法

      注意1: default修飾符必須要加上,否則出錯(cuò)

      注意2: 實(shí)現(xiàn)類中要是想重寫接口中的非抽象方法,那么default修飾符必須不能加,否則出錯(cuò)

      代碼示例:

      public interface TestInterface {
          //常量:
          public static final int NUM= 10;
          //抽象方法:
          public abstract void a();
          //public default修飾的非抽象方法:
          public default void b(){
              System.out.println("-------TestInterface---b()-----");
          }
      }
      class Test implements TestInterface{
          public void c(){
              //用一下接口中的b方法:
              b();//可以
              //super.b();不可以
              TestInterface.super.b();//可以
          }
          @Override
          public void a() {
              System.out.println("重寫了a方法");
          }
          @Override
          public void b() {
          }
      }
      
  1. 新增靜態(tài)態(tài)方法

    注意1: static 不能省略

    注意2: 靜態(tài)方法不能被重寫

    代碼示例:

    public interface TestInterface2 {
        //常量:
        public static final int NUM = 10;
        //抽象方法:
        public abstract  void a();
        //public default非抽象方法;
        public default void b(){
            System.out.println("-----TestInterface2---b");
        }
        //靜態(tài)方法:
        public static void c(){
            System.out.println("TestInterface2中的靜態(tài)方法");
        }
    }
    class Demo implements TestInterface2{
        @Override
        public void a() {
            System.out.println("重寫了a方法");
        }
        public static void c(){
            System.out.println("Demo中的靜態(tài)方法");
        }
    }
    class A {
        //這是一個(gè)main方法,是程序的入口:
        public static void main(String[] args) {
            Demo d = new Demo();
            d.c();
            Demo.c();
            TestInterface2.c();
        }
    }
    
  1. 為什么要加入非抽象方法

    如果接口中只能定義抽象方法的話,那么我要是修改接口中的內(nèi)容,那么對實(shí)現(xiàn)類的影響太大了,所有實(shí)現(xiàn)類都會(huì)受到影響。
    現(xiàn)在在接口中加入非抽象方法,對實(shí)現(xiàn)類沒有影響,想調(diào)用就去調(diào)用即可。

17. 內(nèi)部類

1. 成員內(nèi)部類
  1. 類的組成: 屬性,方法,構(gòu)造器,代碼塊(普通塊,靜態(tài)塊,構(gòu)造塊,同步塊),內(nèi)部類

  2. 定義: 一個(gè)類內(nèi)部的類叫內(nèi)部類: 一個(gè)類TestOuter的內(nèi)部的類SubTest叫內(nèi)部類, 內(nèi)部類 :SubTest 外部類:TestOuter

  3. 內(nèi)部類分類:

    成員內(nèi)部類: 和方法同級

    里面有成員, 方法, 構(gòu)造器等, 和外部類一樣

    修飾符:private,default,protect,public,final,abstract

  4. 靜態(tài)內(nèi)部類就是加了static修飾符的內(nèi)部類

  5. 內(nèi)部類可以訪問外部類的內(nèi)容

  6. 靜態(tài)內(nèi)部類中只能訪問外部類中被static修飾的內(nèi)容

  7. 外部類想要訪問內(nèi)部類的東西,需要?jiǎng)?chuàng)建內(nèi)部類的對象然后進(jìn)行調(diào)用

    D d = new D();
    System.out.println(d.name);
    d.method();
    
  8. 內(nèi)部類和外部類屬性重名的時(shí)候,如何進(jìn)行調(diào)用

    System.out.println(age);//30  內(nèi)部類中的方法變量
    System.out.println(this.age);//20    內(nèi)不類中的變量
    System.out.println(TestOuter.this.age);//10  外部類中的變量
    
  9. 內(nèi)部類創(chuàng)建對象

    1. 靜態(tài)成員內(nèi)部類創(chuàng)建對象

      TestOuter.E e = new TestOuter.E(); # E為內(nèi)部類

    2. 非靜態(tài)成員內(nèi)部類創(chuàng)建對象

      TestOuter t = new TestOuter();
      TestOuter.D d = t.new D();

  10. 代碼示例

    package com.msb.test07;
    /**
     * 1.類的組成:屬性,方法,構(gòu)造器,代碼塊(普通塊,靜態(tài)塊,構(gòu)造塊,同步塊),內(nèi)部類
     * 2.一個(gè)類TestOuter的內(nèi)部的類SubTest叫內(nèi)部類, 內(nèi)部類 :SubTest  外部類:TestOuter
     * 3.內(nèi)部類:成員內(nèi)部類 (靜態(tài)的,非靜態(tài)的) 和  局部內(nèi)部類(位置:方法內(nèi),塊內(nèi),構(gòu)造器內(nèi))
     * 4.成員內(nèi)部類:
     *      里面屬性,方法,構(gòu)造器等
     *      修飾符:private,default,protect,public,final,abstract
     */
    public class TestOuter {
        //非靜態(tài)的成員內(nèi)部類:
        public class D{
            int age = 20;
            String name;
            public void method(){
                //5.內(nèi)部類可以訪問外部類的內(nèi)容
                /*System.out.println(age);
                a();*/
                int age = 30;
                //8.內(nèi)部類和外部類屬性重名的時(shí)候,如何進(jìn)行調(diào)用:
                System.out.println(age);//30
                System.out.println(this.age);//20
                System.out.println(TestOuter.this.age);//10
            }
        }
        //靜態(tài)成員內(nèi)部類:
        static class E{
            public void method(){
                //6.靜態(tài)內(nèi)部類中只能訪問外部類中被static修飾的內(nèi)容
                /*System.out.println(age);
                a();*/
            }
        }
        //屬性:
        int age = 10;
        //方法:
        public void a(){
            System.out.println("這是a方法");
            {
                System.out.println("這是一個(gè)普通塊");
                class B{
                }
            }
            class A{
            }
            //7.外部類想要訪問內(nèi)部類的東西,需要?jiǎng)?chuàng)建內(nèi)部類的對象然后進(jìn)行調(diào)用
            D d = new D();
            System.out.println(d.name);
            d.method();
        }
        static{
            System.out.println("這是靜態(tài)塊");
        }
        {
            System.out.println("這是構(gòu)造塊");
        }
        //構(gòu)造器:
        public TestOuter(){
            class C{
            }
        }
        public TestOuter(int age) {
            this.age = age;
        }
    }
    class Demo{
        //這是一個(gè)main方法,是程序的入口:
        public static void main(String[] args) {
            //創(chuàng)建外部類的對象:
            TestOuter to = new TestOuter();
            to.a();
            //9.創(chuàng)建內(nèi)部類的對象:
            //靜態(tài)的成員內(nèi)部類創(chuàng)建對象:
            TestOuter.E e = new TestOuter.E();
            //非靜態(tài)的成員內(nèi)部類創(chuàng)建對象:
            //錯(cuò)誤:TestOuter.D d = new TestOuter.D();
            TestOuter t = new TestOuter();
            TestOuter.D d = t.new D();
        }
    }
    
    
2.局部內(nèi)部類
package com.msb.test08;
/**
 * @Auther: msb-zhaoss
 */
public class TestOuter {
    //1.在局部內(nèi)部類中訪問到的變量必須是被final修飾的
    public void method(){
        final int num = 10;
        class A{
            public void a(){
                //num = 20;
                System.out.println(num);
            }
        }
    }
    //2.如果類B在整個(gè)項(xiàng)目中只使用一次,那么就沒有必要單獨(dú)創(chuàng)建一個(gè)B類,使用內(nèi)部類就可以了
    public Comparable method2(){
        class B implements Comparable{
            @Override
            public int compareTo(Object o) {
                return 100;
            }
        }
        return new B();
    }
    public Comparable method3(){
        //3.匿名內(nèi)部類
        return new Comparable(){
            @Override
            public int compareTo(Object o) {
                return 200;
            }
        };
    }
    public void teat(){
        Comparable com = new Comparable(){
            @Override
            public int compareTo(Object o) {
                return 200;
            }
        };
        System.out.println(com.compareTo("abc"));
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容