多型,內部類,基本API
阿新 • • 發佈:2022-05-25
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() 返回當前時間(以毫秒為單位)