1. 程式人生 > 其它 >多型,內部類,基本API

多型,內部類,基本API

day03-多型 ,內部類,常用API

今日目標

  • 多型
  • 內部類
  • 常用API

1 多型

1.1 面向物件三大特徵 ?

  • 封裝 , 繼承 , 多型

1.2 什麼是多型 ?

  • 一個物件在不同時刻體現出來的不同形態

  • 舉例 : 一隻貓物件

    • 我們可以說貓就是貓 : Cat cat = new Cat();
    • 我們也可以說貓是動物 : Animal cat = new Cat();
    • 這裡物件在不同時刻,體現出來的不同形態 , 我們就可以理解為多型

1.3 多型的前提

  • 有繼承/實現關係
  • 有方法重寫
  • 父類的引用指向子類的物件
package com.itheima.polymorphism_demo;
/*
    多型的三個前提條件
        1 需要有繼承/實現關係
        2 需要有方法重寫
        3 父類的引用指向子類的物件
 */
public class AnimalTest {
    public static void main(String[] args) {
        // 3 父類的引用指向子類的物件
        // 多型形式物件
        Animal a = new Cat();
    }
}

class Animal{
    public void eat(){
        System.out.println("吃東西");
    }
}

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

1.4 多型的成員訪問特點

  • 構造方法 : 和繼承一樣 , 子類通過super()訪問父類的構造方法
  • 成員變數 : 編譯看左邊(父類) , 執行看左邊(父類)
  • 成員方法 : 編譯看左邊(父類) , 執行看右邊(子類)
package com.itheima.polymorphism_demo;

/*
    多型的成員訪問特點 :
        1 構造方法 : 和繼承一樣 , 都是通過super()訪問父類的構造方法
        2 成員變數 : 編譯看左邊(父類) , 執行看左邊(父類)
        3 成員方法 : 編譯看左邊(父類) , 執行看右邊(子類) , 注意 , 如果執行時
            1) 子類沒有回動態去找父類中的方法
            2) 子類的特有方法無法進行呼叫(多型的缺點)
 */
public class MemberTest {
    public static void main(String[] args) {
        // 父類的引用指向子類的物件
        Fu f = new Zi();

        // 多型物件呼叫成員變數
        System.out.println(f.num);

        // 多型對新鄉呼叫呼叫成員方法
        f.show();

        // 多型物件不能呼叫子類特有的方法
        // f.show2();
    }
}

class Fu {
    int num = 100;

    public void show() {
        System.out.println("父類的show方法");
    }
}

class Zi extends Fu {
    int num = 10;

    public void show() {
        System.out.println("子類的show方法");
    }

    public void show2(){
        System.out.println("子類特有的方法");
    }
}

1.5 多型的優缺點

  • 優點 : 提高程式碼的擴充套件性
  • 缺點 : 不能呼叫子類特有的功能
package com.itheima.polymorphism_test;

public abstract class Animal {
    private String breed;
    private String color;

    public Animal() {
    }

    public Animal(String breed, String color) {
        this.breed = breed;
        this.color = color;
    }

    public String getBreed() {
        return breed;
    }

    public void setBreed(String breed) {
        this.breed = breed;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public abstract void eat();
}

package com.itheima.polymorphism_test;

public class Cat extends Animal {
    public Cat() {
    }

    public Cat(String breed, String color) {
        super(breed, color);
    }

    @Override
    public void eat() {
        System.out.println("貓吃魚...");
    }

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

package com.itheima.polymorphism_test;

public class Dog extends Animal {
    public Dog() {
    }

    public Dog(String breed, String color) {
        super(breed, color);
    }

    @Override
    public void eat() {
        System.out.println("狗吃骨頭!");
    }

    public void lookDoor(){
        System.out.println("狗看門...");
    }
}

package com.itheima.polymorphism_test;

public class Pig extends Animal {
    public Pig() {
    }

    public Pig(String breed, String color) {
        super(breed, color);
    }

    @Override
    public void eat() {
        System.out.println("豬拱白菜...");
    }

    public void sleep() {
        System.out.println("一直再睡...");
    }
}

package com.itheima.polymorphism_test;

/*
    如果方法的引數是一個類的話 , 那麼呼叫此方法需要傳入此類的物件 , 或者子類物件

    多型的好處 :
        提高程式碼的擴充套件性 , 靈活性
    多型的缺點:
        不能呼叫子類的特有功能
 */
public class AnimalTest {
    public static void main(String[] args) {
        useAnimal(new Cat());

        System.out.println("---------");

        useAnimal(new Dog());

        System.out.println("---------");

        useAnimal(new Pig());
    }

    public static void useAnimal(Animal a){// Animal a = new Dog()
        a.eat();
        // 多型不能訪問子類特有的功能
        // 如果解決 ?

        // 向下轉型
        if(a instanceof Cat) {
            Cat cat = (Cat) a;
            cat.catchMouse();
        }
        if(a instanceof Dog) {
            Dog dog = (Dog) a;
            dog.lookDoor();
        }

        if(a instanceof Pig) {
            ((Pig) a).sleep();
        }
    }

//    // 定義一個使用貓類的方法
//    public static void useAnimal(Cat c) {// Cat c = new Cat();
//        c.eat();
//        c.catchMouse();
//    }
//
//    // 定義一個使用狗類的方法
//    public static void useAnimal(Dog d) {// Dog d = new Dog();
//        d.eat();
//        d.lookDoor();
//    }
//
//    // 定義一個使用豬類的方法
//    public static void useAnimal(Pig pig) {
//        pig.eat();
//        pig.sleep();
//    }
}

1.6 多型的轉型

  • 向上轉型 : 把子類型別資料轉成父類型別資料 Animal a = new Cat();
  • 向下轉型 : 把父類型別資料轉成子類型別資料 Cat cat = (Cat)a;

1.7 多型的轉型注意

  • 如果被轉的物件 , 對應的實際型別和目標型別不是同一種資料型別 , 那麼轉換時會出現ClassCastException異常

  • 異常程式碼如下
    public static void main(String[] args) {
        Animal a = new Cat();
        useAnimal(a);
    }
    public static void useAnimal(Animal a) {
        Dog d = (Dog) a;
        d.eat();
    }
    
    

1.8 解決轉型安全隱患

  • 使用關鍵字 instanceof
  • 作用 : 判斷一個物件是否屬於一種引用資料型別
  • 格式 : 物件名 instanceof 引用資料型別
    • 通俗的理解:判斷關鍵字左邊的變數,是否是右邊的型別,返回boolean型別結果

2 內部類

2.1 內部類的分類

  • 什麼是內部類 ?
    • 一個A類 中 定義一個B類 , 那麼B類就屬於A類的內部類 , A類就屬於B類的外部類
  • 什麼時候使用內部類 ?
    • 多個事物之間有包含關係, 可以使用內部類
  • 內部類分類 ?
    • 成員內部類
    • 區域性內部類
    • 匿名內部類

2.2 成員內部類

  • 定義的位置 : 類中方法外

  • 建立成員內部類物件格式 : 外部類名.內部類名 物件名 = new 外部類名().new 內部類名(引數);

    package com.itheima.innerclass_demo.member_innerclass;
    
    // 外部類
    public class Person {
        // 成員內部類
        public class Heart {
            // 頻率變數
            private int rate;
            // 跳動方法
            public void beats() {
                System.out.println("咚咚咚!");
            }
        }
    }
    
    class Test {
        public static void main(String[] args) {
            // 建立內部類物件
            Person.Heart heart = new Person().new Heart();
            // 呼叫內部類中的方法
            heart.beats();
        }
    }
    
  • 成員內部類訪問外部類的成員
    • 在內部類中有代表外部類物件的格式 : 外部類名的.this , 私有的也可以訪問
    • 外部類要想訪問內部類成員 , 需要建立內部類物件
    package com.itheima.innerclass_demo.member_innerclass;
    
    public class Person {
        private String name = "張三";
        private int num = 10;
        
        // 成員內部類
        public class Heart {
            int num = 100;
            // 頻率
            private int rate;
            // 跳動
            public void beats() {
                System.out.println("咚咚咚!");
            }
            // 呼叫外部類的成員
            public void show(){
                int num = 1000;
                System.out.println(Person.this.name);
                System.out.println(num);// 1000 就近原則
                System.out.println(this.num);// 100
                System.out.println(Person.this.num);// 10
    
            }
        }
    }
    
    class Test {
        public static void main(String[] args) {
            Person.Heart heart = new Person().new Heart();
            heart.beats();
            heart.show();
        }
    }
    

2.3 匿名內部類

  • 匿名內部類 : 沒有名字的類 , 一次性產品
  • 使用場景 : 直接呼叫方法 , 作為方法的傳參 , 返回值型別
  • 好處 : 簡化程式碼 , 快速實現介面或者抽象的抽象方法
  • 格式 :
    • new 類名/介面名(){ 重寫抽象方法 } 注意 : 此處建立的是子類物件!!!
  • 使用方式 :
    • 直接呼叫方法
    • 作為方法的引數傳遞
    • 作為方法的返回值型別
//介面
interface Flyable {
    void fly();
}
// 直接呼叫方法
Flyable f1 = new Flyable() {
    @Override
    public void fly() {
        System.out.println("不知道什麼在飛.....");
    }
};
f1.fly();
// 作為方法的引數傳遞
showFlyable(
    new Flyable() {
        @Override
        public void fly() {
            System.out.println("不知道什麼在飛3333");
        }
    }
);

public static void showFlyable(Flyable flyable) {
	flyable.fly();
}
// 作為方法的返回值型別
public static Flyable getFlyable() {
	return new Flyable() {
        @Override
        public void fly() {
            System.out.println("3333333333333");
        }
    };
}
package com.itheima.innerclass_demo.anonymous_innerclass;

/*
    1 如果方法的引數是一個類的話 , 呼叫此方法需要傳入此類的物件或者此類的子類物件
    2 如果方法的返回值型別是一個類的話 , 需要返回此類的物件 , 或者此類的子類物件

     3 如果方法的引數是一個介面的話 , 呼叫此方法需要傳入此介面的實現類物件
     4 如果方法的返回值型別是一個介面的話 , 需要返回此介面的實現類物件


     匿名內部類 : 代表的就是子類物件!!!
        new 類名/介面名(){
            重寫抽象類或者介面中的抽象方法
        };

     使用方向 :
        1 呼叫方法
        2 作為方法引數傳遞
        3 作為方法的返回值
 */
public interface Swim {
    public abstract void swimming();
}

class Test {
    public static void main(String[] args) {
//        // 子類物件!!!
        //  1 呼叫方法
//       new Swim() {
//            @Override
//            public void swimming() {
//                System.out.println("匿名內部類 , 重寫了介面中的抽象方法...");
//            }
//        }.swimming();


//        //   2 作為方法引數傳遞
//        useSwim(new Swim() {
//            @Override
//            public void swimming() {
//                System.out.println("匿名內部類 , 重寫了介面中的抽象方法...");
//            }
//        });

//        // 3 作為方法的返回值
//        Swim s = getSwim();
//        s.swimming();
    }


    public static Swim getSwim() {
        return new Swim() {
            @Override
            public void swimming() {
                System.out.println("匿名內部類 , 重寫了介面中的抽象方法...");
            }
        };
    }


    /*
        Swim swim = new Swim() {
            @Override
            public void swimming() {
                System.out.println("匿名內部類 , 重寫了介面中的抽象方法...");
            }
        };
     */
    public static void useSwim(Swim swim) {
        swim.swimming();
    }
}

3 API

3.1 Object類

  • 概述 : 類Object是類層次結構的根,每個類都把Object作為超類。 所有物件(包括陣列)都實現了這個類的方法
  • 方法 : public String toString()
    • 如果一個類沒有重寫toString方法 , 那麼列印此類的物件 , 列印的是此物件的地址值
    • 如果一個類重寫了toString方法 , 那麼列印此類的物件 , 列印的是此物件的屬性值
    • 好處 : 把物件轉成字串 , 快速檢視一個物件的屬性值
    • 執行時機 : 列印物件時會預設呼叫toString方法
  • 方法 : public boolean equals()
    • 如果一個類沒有重寫equals方法 , 那麼比較此類的物件 . 比較的是地址值
    • 如果一個類重寫了equals方法 . 那麼比較此類的物件 , 比較的是屬性值是否相等
    • 好處 : 可以比較物件的內容

3.2 Objects類

  • Objects是JDK1.7新增的一個物件工具類,裡面都是靜態方法可以用來操作物件。比如物件的比較,計算物件的hash值,判斷對手是否為空....比如裡面的equals方法,可以避免空指標異常
public static boolean equals(Object a, Object b):判斷兩個物件是否相等
    
public static boolean equals(Object a, Object b) {
    return (a == b) || (a != null && a.equals(b));
}
a.equals(b) :如果a是null值,肯定會空指標
Objects.equals(a,b);:如果a是null,不會導致空指標異常

3.2 Date類

  • 概述 : java.util.Date 表示特定的瞬間,精確到毫秒
  • 構造方法 :
    • public Date(): 建立的物件,表示的是當前計算機系統的時間
    • public Date(long time): Date物件 = 1970/1/1 0:0:0 + time毫秒值
  • 成員方法 :
    • public long getTime(): 返回毫秒值 = 當前Date代表的時間 - 1970/1/1 0:0:0
    • public void setTime(long t): Date物件 = 1970/1/1 0:0:0 + time毫秒值
package com.itheima.api_demo.date_demo;

import java.util.Date;

/*
    Date類 : 代表的是一個瞬間 , 精確到毫秒

    構造方法 :
        public Date() : 代表的是當前系統時間
        public Date(long date) : Date物件 = 1970/1/1 0:0:0 + long型別的毫秒值

    成員方法 :
        public void setTime(long date) : Date物件 = 1970/1/1 0:0:0 + long型別的毫秒值
        public long getTime() : 返回的是毫秒值 = Date代表的時間 - 1970/1/1 0:0:0
 */
public class DateDemo {
    public static void main(String[] args) {
        //  public Date() : 代表的是當前系統時間
//        Date d = new Date();
//        System.out.println(d);

        //  public Date(long date) : Date物件 = 1970/1/1 0:0:0 + long型別的毫秒值
//        Date d2 = new Date(1000L * 60 * 60 * 24); // 1970/1/1 0:0:0 + 一天的毫秒值
//        System.out.println(d2);

        Date d = new Date();
        // public void setTime(long date) : Date物件 = 1970/1/1 0:0:0 + long型別的毫秒值
        // d.setTime(1000L * 60 * 60 * 24);
        System.out.println(d);

        // public long getTime() : 返回的是毫秒值 = Date代表的時間 - 1970/1/1 0:0:0
        // System.out.println(d.getTime());

    }
}

3.3 DateFormat類

  • 概述 : 主要用於操作日期格式的一個類

  • 作用 :

    • 格式化 : Date --> String
    • 解析 : String --> Date
  • 構造方法 :

    • SimpleDateFormat(String pattern) 給定日期模板建立日期格式化物件
  • 成員方法 :

    • public String format ( Date d ):格式化,將日期物件格式化為字串
    • public Date parse ( String s ):解析,將字串解析為日期物件
package com.itheima.api_demo.dateformat_demo;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/*
    SimpleDateFormat類 :
        "2021年04月03日 16:48:10"  ---> Date
        Date(Sat Apr 03 16:41:38 CST 2021) --> "2021年04月03日 16:48:10"

        作用 :
            格式化 : Date --> String
            解析   : String --> Date

        構造方法 :
            public SimpleDateFormat(String pattern) : pattern : 字串型別的日期模板

        成員方法 ;
            public final String format(Date date) : 接收一個Date物件返回指定模式的字串
            public Date parse(String source) : 接收一個字串  , 返回一個Date物件



        1 獲取當前的日期物件,使用格式:yyyy-MM-dd HH:mm:ss 來表示,例如:2020-10-31 17:00:00【格式化】

        2 將字串的 2020年10月31日  17:00:00,轉換為日期Date物件。【解析】

 */
public class SimpleDateFormatDemo {
    public static void main(String[] args) throws ParseException {
        // 解析   : String --> Date
        String strDate = "2020年10月31日 17:00:00";
        // 注意 : 解析時 , SimpleDateFormat的引數(日期模板) , 必須和要解析字串的模式匹配
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        //  public Date parse(String source) : 接收一個字串  , 返回一個Date物件
        Date date = sdf.parse(strDate);
        System.out.println(date); // Sat Oct 31 17:00:00 CST 2020
    }

    private static void method() {
        // 格式化 : Date --> String
        // 獲取當前系統時間
        Date date = new Date();
        // System.out.println(date);// Sat Apr 03 16:53:35 CST 2021

        // public SimpleDateFormat(String pattern) : pattern : 字串型別的日期模板
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd ");

        // public final String format(Date date) : 接收一個Date物件返回指定模式的字串
        String strDate = sdf.format(date);

        System.out.println(strDate);
    }
}
戰狼	吳京	120.0	0.0	20.0	120	19-12-12 下午12:12

3.4 Calendar類

  • 概述 :
    • java.util.Calendar類表示日曆,內含有各種時間資訊,以及獲取,計算時間的方法。
    • Calendar本身是一個抽象類,可以通過Calendar提供的靜態方法getInstance日曆子類物件
  • Calendar常用方法 :
    方法名 說明
    public static Calendar getInstance() 獲取一個它的子類GregorianCalendar物件。
    public int get(int field) 獲取指定日曆欄位的時間值。
    public void set(int field,int value) 設定指定欄位的時間值
    public void add(int field,int amount) 為某個欄位增加/減少指定的值
  • get,set,add方法引數中都有一個整數型別的引數field,field用來區分當前要獲取或者操作的日期時間資料的。field資料的值使用Calender中定義的整數常量來表示

    • Calendar.YEAR : 年
    • Calendar.MONTH :月
    • Calendar.DAY_OF_MONTH:月中的周
    • Calendar.HOUR:小時
    • Calendar.MINUTE:分鐘,
    • Calendar.SECOND:秒
    • Calendar.DAY_OF_WEEK:星期
  • 星期對應的關係

    ​ 欄位時間值 : 1 2 3 ... 7
    ​ 真正的時間 : SUNDAY MONDAY TUESDAY ... SATURDAY

  • 月份對應的關係

    ​ 欄位時間值 : 0 1 .... 11
    ​ 正真的時間 : JANUARY FEBRUARY .... DECEMBER

package com.itheima.api_demo.calendar_demo;
/*

    月份對應的關係
    欄位時間值     :       0           1           ....        11
    正真的時間     :     JANUARY     FEBRUARY      ....      DECEMBER


 */
import java.util.Calendar;
/*
    成員方法 :
        public int get(int field)	獲取指定日曆欄位的時間值。
        public void set(int field,int value)	設定指定欄位的時間值
        public void add(int field,int amount)	為某個欄位增加/減少指定的值
 */
public class CalendarDemo {
    public static void main(String[] args) {
        // 獲取Calendar物件 , rightNow物件
        Calendar rightNow = Calendar.getInstance();

        // public void set(int field , int value)	設定指定欄位的時間值
        // rightNow.set(Calendar.YEAR , 2024);
        // rightNow.set(Calendar.MONTH , 5);
        // rightNow.set(Calendar.DAY_OF_MONTH, 10);

        // public void add(int field,int amount)	為某個欄位增加/減少指定的值
        // rightNow.add(Calendar.DAY_OF_MONTH , -3);

        //  public int get(int field)	 : 獲取指定日曆欄位的時間值。
        int year = rightNow.get(Calendar.YEAR);
        int month = rightNow.get(Calendar.MONTH);
        int day = rightNow.get(Calendar.DAY_OF_MONTH);


        System.out.println(year); // 2021
        System.out.println(month);// 3
        System.out.println(day);  // 3
    }
}
package com.itheima.api_demo.calendar_demo;

import java.util.Calendar;

/*
    1 寫程式碼使用get方法,將年,月,日,時,分,秒,周獲取出來
    特別注意獲取月份,和星期有以下特點:
    直接獲取的月份資料是從0開始的, 0表示1月,.....11表示12月
    周的獲取,從週日開始計算,1就是週日,2就是週一 ......7就是週六


星期對應的關係
     欄位時間值  :   1           2            3          ...        7
     真正的時間  : SUNDAY        MONDAY      TUESDAY     ...        SATURDAY

月份對應的關係
    欄位時間值     :       0           1           ....        11
    正真的時間     :     JANUARY     FEBRUARY      ....      DECEMBER

 */
public class Test1 {
    public static void main(String[] args) {
        // 拿到當前時間
        Calendar now = Calendar.getInstance();

        System.out.println(now.get(Calendar.YEAR));
        System.out.println(now.get(Calendar.MONTH));
        System.out.println(now.get(Calendar.DAY_OF_MONTH));
        System.out.println(now.get(Calendar.HOUR));
        System.out.println(now.get(Calendar.MINUTE));
        System.out.println(now.get(Calendar.SECOND));

        int week = now.get(Calendar.DAY_OF_WEEK);// 7
        System.out.println(getWeek(week));// 欄位值
    }

    public static String getWeek(int field){
        String[] str = { "" , "SUNDAY" , "MONDAY" , "TUESDAY" , "WEDNESDAY" , "THURSDAY" , "FRIDAY" , "SATURDAY"};
        return str[field];
    }
}
package com.itheima.api_demo.calendar_demo;

import java.util.Calendar;

/*
    2 寫程式碼實現,獲取2022年10月1日是星期幾?
    參考思路:
    直接獲取日曆物件,得到的是當前系統的日曆時間資訊。
    獲取日曆物件後,要重新設定日期
    再獲取星期資料

 */
public class Test2 {
    public static void main(String[] args) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, 2022);
        cal.set(Calendar.MONTH, 9);
        cal.set(Calendar.DAY_OF_MONTH, 1);

        int week = cal.get(Calendar.DAY_OF_WEEK);
        System.out.println(getWeek(week));// 欄位值
    }

    public static String getWeek(int field){
        String[] str = { "" , "SUNDAY" , "MONDAY" , "TUESDAY" , "WEDNESDAY" , "THURSDAY" , "FRIDAY" , "SATURDAY"};
        return str[field];
    }
}

package com.itheima.api_demo.calendar_demo;

import java.util.Calendar;

/*
    3 計算10000天之後的年月日

    參考思路:
    先獲取當前日曆物件
    再呼叫add方法,指定DATE或者DAY_OF_MONTH,新增10000天
    再獲取日曆的年,月,日

 */
public class Test3 {
    public static void main(String[] args) {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_MONTH, 10000);


        System.out.println(cal.get(Calendar.YEAR));
        System.out.println(cal.get(Calendar.MONTH));
        System.out.println(cal.get(Calendar.DAY_OF_MONTH));
    }
}

3.5 Math類

  • 概述 : Math包含執行基本數字運算的方法,如基本指數,對數,平方根和三角函式。所提供的都是靜態方法,可以直接呼叫

  • 常用方法 :

    public static int abs(int a) 獲取引數a的絕對值:
    public static double ceil(double a) 向上取整
    public static double floor(double a) 向下取整
    public static double pow(double a, double b) 獲取a的b次冪
    public static long round(double a) 四捨五入取整

3.6 System類

  • System類包含幾個有用的類欄位和方法。 它不能被例項化

  • 常用方法 :

    方法名 說明
    public static void exit(int status) 終止當前執行的 Java 虛擬機器,非零表示異常終止
    public static long currentTimeMillis() 返回當前時間(以毫秒為單位)