第一小節 抽象類
1.抽象類格式和概念
//有抽象方法的類,一定是抽象類
abstract class Demo1{
//被`abstract`修飾的都是抽象方法
public abstract void speak()
}
//抽象類不一定有抽象方法
abstract class Demo2{
//普通方法
public void speak()
}
3.代碼演示
//定義形狀
public abstract class Shape {
//抽象類中的普通成員變量
private double chang;
private double kuan;
//抽象類有可以有構造方法
public Shape() {}
public Shape(double chang, double kuan) {
this.chang = chang;
this.kuan = kuan;
}
//抽象類中可以有普通方法
public void method1(){
System.out.println("1");
}
//抽象方法 有抽象方法的類一定是抽象類
public abstract void method2();
}
//繼承抽象類一定要實現抽象方法,如果不實現,這個類還是抽象類, 編譯的時候會有提示的
abstract class Test2 extends Shape{
}
//繼承
class Test extends Shape{
//繼承抽象類一定要實現抽象方法
@Override
public void method2() {
}
public static void main(String[] args) {
// 抽象類不能實例化
// Shape b = new Shape();
Test test = new Test();
}
}
3.抽象類的作用
用來描述一種數據類型應該具備的基本特徵(成員變量)和行爲(方法),如何實現這些方法由子類通過方法重寫完成。
4.抽象類的特點
- 1.抽象類和抽象方法都需要用關鍵字:abstract修飾
- 2.抽象類不能直接創建對象,因爲調用抽象方法毫無意義,爲什麼沒有意義呢,
因爲抽象方法 沒有代碼塊,它只是定義了方法
- 3.子類繼承抽象類之後,要實現抽象類中的所有抽象方法,否則要將子類也定義爲抽象類
5.抽象類常見的幾個問題描述
- 5.1抽象類不能創建對象,抽象類中是有構造方法,子類可以通過super調用父類的構造方法,給父類的成員變量賦值,賦值完之後子類就可以使用父類繼承的成員變量。
- 5.2抽象類一定是個父類,因爲抽象類不能創建對象。
- 5.3抽象類中可以不定義抽象方法
- 5.4抽象類中可以定義普通方法(有方法體的方法)
- 5.5抽象關鍵字不能和private關鍵字共存。因爲private修飾的方法不能被子類重寫,而抽象方法又要求子類要重寫。
第二小節 接口
1.接口的概念
- 1.1接口也是一種數據類型。它是比抽象類更加抽象的’類’
- 1.2接口是功能(方法)的集合,如何實現這些功能由實現類(子類)通過方法重寫實現。
- 1.3接口中的方法都是抽象方法。
2.接口的定義和使用格式
//定義格式
interface 接口名{
// 抽象方法
}
//使用格式
class 類名 implements 接口名 {
// 重寫抽象方法
}
3.示例代碼
//抽象類(父類)
public abstract class Animal {
// 動物都會叫 但是每個動物叫聲都不一樣 所有定義一個抽象方法
public abstract void jiao();
}
//定義個子類dog繼承動物類
public class Dog extends Animal{
@Override
public void jiao() {
System.out.println("汪汪汪");
}
}
//定義格式
interface 接口名{
// 抽象方法
}
//寫一個接口給actdog 因爲不是每個狗都會表演
public interface jiekou {
// 抽象方法
public abstract void actDog();
}
//寫一個會表演的狗繼承狗類 並且使用接口
public class ActDog extends Dog implements jiekou {
@Override
public void actDog() {
System.out.println("會胸口碎大石");
}
}
//寫一個測試類進行測試
public class Demo2 {
public static void main(String[] args) {
ActDog dog = new ActDog();
dog.jiao();
dog.actDog();
Dog dog1 = new Dog();
dog1.jiao();
// 因爲不是每一個狗都會表演 所以dog1不能調用act方法
// dog1.actDog();
}
}
4. 接口的特點和注意事項
4.1 接口特點
在JDK1.8之前,接口中所有的方法都是抽象方法,在JDK1.8後,接口中的方法可以有默認實現(有方法體)
public interface jiekou {
// 抽象方法
public abstract void actDog();
//默認方法
public static void eat() {
System.out.println("會吃東西");
};
}
接口沒有構造方法
接口中定義成員變量是常量。
接口不能創建對象,原理跟抽象方法一樣,因爲沒有代碼塊(也是沒有具體的實現方法)
接口可以繼承接口,而且可以多繼承。
接口中的抽象方法有默認的修飾符:
public abstract
接口中的常量有默認的修飾符:
public static final
4.2 注意事項
Java支持類在繼承一個類的同時實現1個或多個接口。
接口與父類的功能可以重複,均代表要具備某種功能,並不衝突。
當一個類實現了接口時,必須實現其所有的方法,否則這個類必須定義爲一個抽象類。
4.3 接口和抽象類的應用
/**
* 適配器模式
*/
interface MyInterface{
//比如定義了n多個方法
void method();
void method2();
void method3();
void method4();
void method5();
void method6();
}
//class Demo implements MyInterface {
//這樣我就要實現很多個方法了,但是我就只是實現第一個方法
//}
abstract class Adapter implements MyInterface{
@Override
public void method() {
}
@Override
public void method2() {
}
@Override
public void method3() {
}
@Override
public void method4() {
}
@Override
public void method5() {
}
@Override
public void method6() {
}
}
class Demo extends Adapter{
@Override
public void method() {
//現在就只需要實現一個方法了
}
}
5. 接口和抽象類的區別
5.1.相同點
- 都不能創建對象
- 子類或實現類都必須重寫抽象方法
5.2.不同點
- 接口可以接口且可以多繼承, 類只能單繼承,不能多繼承。
- 接口中的成員變量是常量了,抽象類可以有普通成員變量,也可以有常量。
- 抽象類中可以有構造方法(因爲抽象類不能new 出來,所以抽象類的構造方法,只有在子類繼承的時候纔可以調用抽象類的構造方法),接口中沒有構造方法
- 接口中的抽象方法有默認的修飾符:public abstract,抽象類的抽象方法沒有默認的修飾符。
- 接口中的常量有默認的修飾符:public static final,抽象類的成員變量沒有默認修飾符。
- 抽象類中可以有非抽象方法,接口在JDK.18(包括1.8)之後纔可以有非抽象方法。
第三小節 多態
1.多態的概述
多態是java面向對象的第三大特徵
,同一種事物表現出來的多種形態則稱爲多態。
比如:張三 ==> 學生 張三 ==> 路人甲 張三 ==> 兒子
比如:狗 ==> 動物 狗 ==> 寵物
2.多態的注意細節,例子,和分析,重點
class Animal{
int num = 10;
static int age = 20;
public void eat(){
System.out.println("動物吃飯");
}
public static void sleep(){
System.out.println("動物睡覺");
}
public void run(){
System.out.println("動物跑步");
}
}
//多態三要素之一:Cat類繼承了Animal類
class Cat extends Animal{
int num = 80;
static int age =90;
String name = "tomcat";
//多態三要素之二:子類要重寫父類的方法,非靜態方法
public void eat(){
System.out.println("貓吃飯");
}
//多態三要素之二:子類要重寫父類的方法,靜態方法
public static void sleep(){
System.out.println("貓睡覺");
}
public void catchMouse(){
System.out.println("貓在抓老鼠");
}
}
class Demo{
public static void main(String[] args) {
//多態三要素之三:父類數據類型的引用指向子類對象
Animal am = new Cat(); //多態的格式,也可以只想接口
am.eat(); //貓吃飯
am.sleep(); //動物在睡覺
am.run(); //動物在奔跑
System.out.println(am.num); //10
System.out.println(am.age); //20
//總結:
//成員變量:編譯看左邊(父類),運行看左邊(父類) --->am.num 和 am.age
//靜態方法:編譯看左邊(父類),運行看左邊(父類) --->sleep() 靜態和類相關,算不上重寫
//成員方法:編譯看左邊(父類),運行看右邊(子類) --->eat()
//多態的好處缺點,不能訪問子類特有的成員:成員變量和成員方法。
//am.catchMouse(); //編譯報錯
//System.out.println(am.name); //編譯報錯
//如果一定要執行am.name
Cat cat = (Cat)am;
System.out.println(cat.name); //tomcat
}
}
大家都知道花木蘭替父從軍的例子,花木蘭替父親花弧從軍。那麼這時候花木蘭是子類,花弧是父類。花弧有自己的成員屬性年齡,姓名,性別。花木蘭也有這些屬性,但是很明顯二者的屬性完全不一樣。花弧有自己的非靜態成員方法‘騎馬殺敵’,同樣花木蘭也遺傳了父親一樣的方法‘騎馬殺敵’。花弧還有一個靜態方法‘自我介紹’,每個人都可以問花弧姓甚名誰。同時花木蘭還有一個自己特有的非靜態成員方法‘塗脂抹粉’。但是,現在花木蘭替父從軍,女扮男裝。這時候相當於父類的引用(花弧這個名字)指向了子類對象(花木蘭這個人),那麼在其他類(其他的人)中訪問子類對象(花木蘭這個人)的成員屬性(姓名,年齡,性別)時,其實看到的都是花木蘭她父親的名字(花弧)、年齡(60歲)、性別(男)。當訪問子類對象(花木蘭這個人)的非靜態成員方法(騎馬打仗)時,其實都是看到花木蘭自己運用十八般武藝在騎馬打仗。當訪問花木蘭的靜態方法時(自我介紹),花木蘭自己都是用她父親的名字信息在向別人作自我介紹。並且這時候花木蘭不能使用自己特有的成員方法‘塗脂抹粉’。
-----多態中的向上轉型
那麼終於一將功成萬骨枯,打仗旗開得勝了,花木蘭告別了戰爭生活。有一天,遇到了自己心愛的男人,這時候愛情的力量將父類對象的引用(花弧這個名字)強制轉換爲子類對象本來的引用(花木蘭這個名字),那麼花木蘭又從新成爲了她自己,這時候她完全是她自己了。名字是花木蘭,年齡是28,性別是女,打仗依然那樣生猛女漢子,自我介紹則堂堂正正地告訴別人我叫花木蘭。OMG!終於,終於可以使用自己特有的成員方法‘塗脂抹粉’了。從此,花木蘭完全回到了替父從軍前的那個花木蘭了。並且和自己心愛的男人幸福的過完了一生。
-----多態中的向下轉型
3.多態的使用場景
//作爲形式參數,多態用於形式參數類型的時候可以接收更多類型的對象
public class Demo2 {
public static void main(String[] args) {
Animal dog = new Dog();
feedAnimal(dog);
Animal p = new pig();
feedAnimal(p);
Animal cat = new cat();
feedAnimal(cat);
}
public static void feedAnimal(Animal a) { //Animal a = new Dog();
a.eat();
}
}
//作爲返回值類型,多態用於返回值類型的時候可以返回更多類型的對象。
public static void main(String[] args) {
Animal a = productAnimal(1);
a.eat();
Animal d4 = productAnimal(2);
d4.eat();
d4.jiao();
Animal d41 = productAnimal(55);
d41.eat();
d41.jiao();
}
//生成動物 type = 1 表示生產狗 type = 2 表示生產貓
public static Animal productAnimal(int type) {
if (type == 1) {
return new Dog();
} else if (type == 2) {
return new cat();
}
return new pig();
}
4.多態的轉型
- 向上轉型
//當把子類對象賦值給一個父類引用時,便是向上轉型,多態本身就是向上轉型的過程。
使用格式 父類類型 變量名 = new 子類類型();
如:Person p = new Student();
向下轉型(參考基本數據類的強制轉換)
子類類型 變量名 = (子類類型) 父類類型的變量; 如:Student stu = (Student) p; //變量p 實際上指向Student對象
5. instanceof關鍵字
5.1.instanceof的作用
用來判斷某個對象是否屬於某種數據類型。如學生的對象屬於學生類,學生的對象也屬於人類。
5.2.使用格式
boolean b = 對象名 instanceof 類名或接口名;
5.3. 注意事項
如果instanceof右邊是類名,則要求左邊的對象名和類名必須存在子父類關係。