第八天(堅持)
抽象類
1.什么是抽象類,作用特點。
抽象類是面向對象編程中一種特殊的類,它不能被實例化,主要用于作為其他類的基類(父類)。抽象類的主要作用是定義公共結構和行為規范,同時強制子類實現特定的功能,常用于將部分代碼抽象到抽象類中。比較典型的就是模板方法模式。
抽象類中可以補定義抽象方法,但抽象方法一定在抽象類中。
注解(抽象類的特點)
1)由abstract修飾的方法為抽象方法,抽象方法沒有方法體,需要使用分號結尾
2)若類中包含抽象方法,那么該類必須使用關鍵字abstract聲明成抽象類,final不能修飾抽象類
3)抽象類里,可以沒有抽象方法
4)抽象類里可以提供構造器,但是不能實例化,沒有意義。
5)一個類繼承了抽象類,那么必須重寫里面的所有抽象方法,除非該子類也聲明為抽象類。
接口
接口中不考慮Java8中default方法情況下,只能定義抽象類。接口主要用于制定規范,一般在實際開發中,我們會先把接口暴露給外部,然后在業務代碼中實現接口。
接口特點
使用interface定義
可以提供成員變量,默認提供public static final進行修飾
可以提供成員方法,默認使用public abtract進行修飾
接口中不能存在構造器,接口不能實例化,
與繼承不同,一個類可以實現多個接口。接口間使用逗號分開。
使用關鍵字implements進行實現,必須實現接口中的所有抽象方法
若一個類中沒有全部實現接口中的抽象方法,那么該類需要使用abstract聲明成抽象類
接口之間可以存在繼承關系,即一個接口通過關鍵字extends可以繼承另一個(或多個)接口。
子接口繼承了父接口中的所有抽象方法
---------------------------------------------------------------------------------------------------------------------------------
接口和抽象類的區別
1.方法定義:接口和抽象類,最明顯的區別就是接口只是定義了一些方法而已,在不考慮Java8中default方法情況下,接口中只有抽象方法,是沒有實現的代碼的。(Java8中可以有默認方法)
2.修飾符:抽象類中的修飾符可以有public、protected和private和<default>這些修飾符,而接口中默認修飾符是public。不可以使用其它修飾符。(接口中,如果定義了成員變量,還必須要初始化)
3.構造器:抽象類可以有構造器必須私有。接口不能有構造器。
4.接口可以被實現,抽象類可以被繼承。一個類可以實現多個接口,一個接口可以繼承多個其他接口但,一個抽象類只能繼承一個抽象類。
5.職責不同:接口和抽象類的職責不一樣。接口主要用于制定規范,一般在實際開發中,我們會先把接口暴露給外部,然后在業務代碼中實現接口。抽象類的主要作用是定義公共結構和行為規范,同時強制子類實現特定的功能,常用于將部分代碼抽象到抽象類中。比較典型的就是模板方法模式。
---------------------------------------------------------------------------------------------------------------------------------
枚舉
在Java中,枚舉是一種特殊的引用數據類型,是一個被命名的整型常數的集合,用于聲明一組帶標識符的常數,枚舉在日常生活中很常見,例如表示星期的SUNDAY、MONDAY、TUESDAY、WEDNESDAY、THURSDAY、FRIDAY、SATURDAY就是一個枚舉。
枚舉特點
使用enum關鍵字定義一個枚舉,默認會繼承java.lang.Enum類,而且是一個final類,因此不能再繼承其他類
必須在枚舉類的第一行聲明枚舉類對象。有多個枚舉對象時,使用逗號隔開,最后一個用分號結尾
可以提供構造器,必須是私有的,如果構造器有形參,定義對象時必須顯式調用構造器
如果使用無參構造器創建枚舉對象,則定義對象時,小括號可以省略
可以提供私有的屬性(建議,如不外部可以修該)
public enum Year{//1. 枚舉的第一行,必須是該枚舉的對象,即你要表達的離散值。多個離散值使用逗號隔開,最后一個值分號結束。JANUARY(1),FEBRUARY(2),MARCH(3),APRIL(4),MAY(5),JUNE(6),JULY(7),AUGUST(8),SEPTEMBER(9),OCTOBER(10),NOVEMBER(11),DECEMBER(12),AAAA; // 如果調用無參構造器,小括號可以省略//2. 枚舉可以提供私有屬性private int number;//3. 可以提供構造器,但是必須是私有的, 實際上枚舉的離散值就是調用構造器產生的,// ? 調用構造器的格式: ? 離散值(有參傳參)private Year(int number){this.number = number;}//4. 構造器可以重載private Year(){}// 5. 可以給私有的成員變量,提供get/set方法, 不建議提供set方法public int getNumber(){return number;} ? ? }
帶有value的枚舉
package com.rs.shuatiwang.model.enums; ? import cn.hutool.core.util.ObjectUtil; ? import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; ? public enum AppTypeEnum { ?SCORE("得分類", 0),TEST("測評類", 1); ?private final String text; ?private final int value; ?AppTypeEnum(String text, int value) {this.text = text;this.value = value;} ?/*** 根據 value 獲取枚舉** @param value* @return*/public static AppTypeEnum getEnumByValue(Integer value) {if (ObjectUtil.isEmpty(value)) {return null;}for (AppTypeEnum anEnum : AppTypeEnum.values()) {if (anEnum.value == value) {return anEnum;}}return null;} ?/*** 獲取值列表** @return*/public static List<Integer> getValues() {return Arrays.stream(values()).map(item -> item.value).collect(Collectors.toList());} ?public int getValue() {return value;} ?public String getText() {return text;} }
內部類
定義在一個類內部的類,就是內部類。內部類可以分為:成員內部類、靜態內部類、局部內部類、匿名內部類。
成員內部類(了解)
定義在一個類的內部,與這個類的成員(屬性、方法)平級,并且沒有用static修飾的類。
1、訪問權限可以是任意的權限,類似于一個類中的成員。
2、實例化的過程,需要先實例化外部類對象,再使用外部類對象進行內部類的實例化
3、內部類編譯后,也會生成.class字節碼文件。格式:外部類$內部類.class
/*** 成員內部類*/ public class Program {public static void main(String[] args) {// 1. 實例化一個外部類的對象Outer outer = new Outer();outer.name = "outer";// 2. 通過外部類的對象,實例化內部類對象Outer.Inner inner = outer.new Inner();inner.name = "inner";inner.show("hello");} } ? /*** 外部類*/ class Outer {public String name;public int age1;// 這個類,由于是書寫在一個類的內部,因此這個類被稱為--內部類// 這個類,由于是寫在Outer類中,和類中的屬性、方法平級,可以稱為是一個類的成員。// 并且,這個類沒有使用 static 修飾,這樣的類,被稱為 -- 成員內部類class Inner {Inner() {System.out.println("實例化了一個Inner的對象");}public String name;public int age2; ?public void show(int age3) {System.out.println("參數age3: " + age3);System.out.println("內部類屬性age2: " + age2);System.out.println("外部類屬性age1: " + age1);} ?public void show(String name) {System.out.println("參數name: " + name);System.out.println("內部類屬性name: " + this.name);System.out.println("外部類屬性name: " + Outer.this.name);}} }
靜態內部類(了解)
定義在一個類的內部,與這個類的成員(屬性、方法)平級,并且使用static修飾的類。
1、訪問權限可以是任意的權限,類似于一個類中的成員。
2、實例化的過程中,直接使用 new實例化一個外部類 .內部類對象即可。
3、內部類編譯后,也會生成.class字節碼文件。格式:外部類$內部類 .class
/*** 靜態內部類*/ public class Program {public static void main(String[] args) {// 1. 實例化靜態內部類對象的時候,不需要借助外部類對象的。// Outer.Inner inner = new Outer.Inner();// 2. 如果已經事先導包了,還可以直接進行實例化Inner inner = new Inner(); ?} } ? class Outer {public String name;// 因為這個類,書寫與Outer類內,并且是用static修飾的類// 這樣的類,被稱為 -- 靜態內部類static class Inner {Inner() {System.out.println("實例化了一個Inner對象");} ?public String name; ?public void show(String name) {System.out.println("參數name: " + name);System.out.println("內部類屬性name: " + this.name);System.out.println("外部類屬性name,此時無法訪問" Outer.this.name);}} }
局部內部類(了解)
定義在某一個代碼段中的中。
1、沒有訪問權限修飾符。
2、在當前方法中,直接實例化即可
3、內部類編譯后,也會生成.class字節碼文件。格式:外部類$序號內部類 .class
public class Program {public static void main(String[] args) {int a;// 寫在某一個局部代碼段中(例如:方法中)// 這個類,只能在當前的方法中使用class Inner { ?}Inner inner = new Inner();test();} ?static void test() {class Inner { ?}} }
4.4 匿名內部類(重點)以及數組自定義排序Comparable接口
匿名內部類是Java中一種特殊的內部類,它沒有顯式的類名,通常用于簡化代碼和實現一次性使用的類。
public class Teacher implements Comparable<Teacher> {private int age;public Teacher(int age) {this.age = age;} public int getAge() {return age; } ? @Override public String toString() {return "Teacher{" +"age=" + age +'}'; } ? @Override public int compareTo(Teacher o) {return this.age - o.age; } }
import java.util.Arrays; import java.util.Comparator; ? public class TeacherTest {public static void main(String[] args) {//定義一個Teacher類型的數組,存儲4個Teacher對象Teacher[] ts = new Teacher[4];for (int i = 0; i < ts.length; i++) {ts[i] = new Teacher((int)(Math.random()*10)+30);}//排序:調用數組工具類的排序方法Arrays.sort(ts);System.out.println(Arrays.toString(ts)); ?//想要在不改變Teacher源碼的情況下,降序/** 匿名內部類:* 1. 寫在方法中。* 2. 因為只在該處使用一次,因此沒有必要定義出來該類的類結構。* 3. 匿名內部類一般都是向上造型這種多態寫法,父類一般都是抽象類或者是接口。* 4. 語法結構:* ? ? 父類型名 變量名 = new 父類型名(){* ? ? ? ? //要重寫的方法* ? ? };*/Comparator c = new Comparator<Teacher>(){public int compare(Teacher o1, Teacher o2) {return o2.getAge()-o1.getAge();}};Arrays.sort(ts, c);System.out.println(Arrays.toString(ts));} ? }