8.7 多態
? ? ? ? 什么是多態? 即同一方法可以根據發送對象的不同而采用多種不同的方式。
? ? ? ? 一個對象的實際類型是確定的,但可以指向對象的引用的類型有很多。在句話我是這樣理解的:
? ? ? ? 在實例中使用方法都是根據他最開始將類實例化最左邊的類型來定的,但是父類引用指向對象子類的話,如果子類有重寫的方法(即方法名與父類相同的方法但是內容不一定相同),那么執行的子類所重寫的方法,如果沒有重寫的方法,就執行父類的。在這句話中所說的“但可以指向對象的引用的類型有很多”,意思是一個父類可以有很多的子類,都可以使用他們的重寫方法。
示例:
父類Person:
package com.oop.demo06;public class Person {public void run(){System.out.println("run");}}
子類Student:
package com.oop.demo06;public class Student extends Person {@Overridepublic void run() {System.out.println("son");}public void eat(){System.out.println("eat");}
}
?測試類:
import com.oop.demo06.Student;
import com.oop.demo06.Person;public class AppLication{public static void main(String[] args) {// 一個對象的實際類型是確定的// 可以指向的引用類型就不確定了:父類的引用指向子類// Student 能調用的方法都是自己的或者繼承父類的!Student S1 = new Student();// Person是父類型的類,可以指向子類,但是不能調用子類獨有的方法Person S2 = new Student();Object S3 = new Student();S2.run(); // 子類重寫了父類的方法,執行子類的方法S1.run();// 對象能執行能執行哪些方法,主要看對象的左邊類型,和右邊關系不大!((Student) S2).eat(); //將S2的類型強制轉換為Student,就可以調用方法了!S1.eat();}
}/*多態注意事項:1. 多態是方法的多態,屬性沒有多態2. 父類和子類要有聯系 類型轉換異常! ClassCastException!3. 存在條件: 繼承關系,方法需要重寫,父類引用指向子類對象!1. static 方法,屬于類,它不屬于實例2. final 常量;3. private 方法*/
8.8 instanceof 和 類型轉換
? ? ? ? instanceof 使用的方法格式:
? ? ? ? 【實例的名稱? ? ? ? instanceof? ? ? ? 類的類型名稱】,判斷一個對象是什么類型,就是判讀兩個類型的對象是否有父子關系,有的話就返回Ture,沒有就是返回False。
? ? ? ? 使用?【實例的名稱? ? ? ? instanceof? ? ? ? 類的類型名稱】時,能否編譯看的是實例化對象的類型名,輸出的結果看的是實例化對象時最右邊的所實例的對象值。
首先父類是Person,其余的類:Student、Teacher是Person的子類。
import com.oop.demo06.Student;
import com.oop.demo06.Person;
import com.oop.demo06.Teacher;public class AppLication{public static void main(String[] args) {// Object > Person > Student// Object > Person > Tercher// Object > StringObject object = new Student();System.out.println(object instanceof Student); // trueSystem.out.println(object instanceof Person); // trueSystem.out.println(object instanceof Object); // trueSystem.out.println(object instanceof Teacher); // falseSystem.out.println(object instanceof String); // falseSystem.out.println("=====================================");Person person = new Student();System.out.println(person instanceof Student); // trueSystem.out.println(person instanceof Person); // trueSystem.out.println(person instanceof Object); // trueSystem.out.println(person instanceof Teacher); // false
// System.out.println(person instanceof String); // 編譯時就報錯了System.out.println("=====================================");Student student = new Student();System.out.println(student instanceof Student); // trueSystem.out.println(student instanceof Person); // trueSystem.out.println(student instanceof Object); // true
// System.out.println(student instanceof Teacher); // 編譯時就報錯
// System.out.println(student instanceof String); // 編譯時就報錯}
}
類型轉換(關于對象的類型):
import com.oop.demo06.Student;
import com.oop.demo06.Person;
import com.oop.demo06.Teacher;public class AppLication{public static void main(String[] args) {// 類型之間的轉化: 父 子// 高 低Person student = new Student();// student 將這個對象轉換為Student的對象類型// 我們就可以使用這個對象類型中的方法了((Student) student).go(); // 這個是高轉低需要強制轉換// 如果是低轉高,子類轉換為父類不需要強制轉換,可能會丟失一些方法!Student student1 = new Student();Person person = student1;}
}
?
8.9 static 關鍵字詳解
? ? ? ? static修飾符有著靜態的意思,使用他代表著這個方法或者元素在類中是與類一起加載的。
package com.oop.demo07;// static
public class Student {private static int age; // 靜態變量 多線程private double score; // 非靜態變量public static void main(String[] args) {Student s1 = new Student();System.out.println(s1.score);System.out.println(age);}
}
????????在類中,還有著代碼塊這種東西,他的優先級比這個構造器還高。
package com.oop.demo07;public class Person {// {
// // 代碼塊(匿名代碼塊)
// }
//
// static {
// // 靜態代碼塊
// }// 第二個執行,可以用來賦初始值{System.out.println("匿名代碼塊");}// 第一個執行,與類一起加載,只執行一次,不管你實例化多少個對象static {System.out.println("靜態代碼塊");}// 第三個執行,構造器public Person(){System.out.println("構造方法");}public static void main(String[] args) {Person person = new Person();System.out.println("==============");Person person1 = new Person();}
}
????????在Java中有許許多多的有用又有趣的類,在這些類中有著許多有用的靜態方法,可以使用下面這個方法直接調用,想查看類的調用位置直接ctrl+左鍵就行。?
package com.oop.demo07;// 導入其他包中的類的靜態方法
import static java.lang.Math.random; // 返回一個隨機數(0,1)
import static java.lang.Math.PI; // 圓周率
public class Test {public static void main(String[] args) {System.out.println(random());System.out.println(PI);}
}
需要注意的是:
? ? ? ? 如果給這些東西使用了常量修飾符final,那么他將會是唯一的,無無法擁有子類。?
?
8.10 抽象類
? ? ? ? 什么是抽象類?abstract?修飾符可以用來修飾方法也可以修飾類,如果修飾方法,那么該方法就是抽象方法;如果修飾類,那么就是抽象類。
? ? ? ? 抽象類中可以沒有抽象方法,但是有抽象方法的類一定要聲明為抽象類。
? ? ? ? 抽象類,不能用new關鍵字來創建對象,它是用來讓子類繼承的。
? ? ? ? 抽象方法,只有方法的聲明,沒有方法的實現,它是用來讓子類實現的。
? ? ? ? 子類繼承了抽象類,那么他就必須要實現抽象類沒有實現的抽象方法,否則該子類也要聲明為抽象類。
抽象父類:
package com.oop.demo08;//abstract 抽象類:類
public abstract class Action {// 約束~有人幫我們實現~// 這個就是抽象的方法,我們只定義了方法名字,他的具體功能由別人實現public abstract void doSomething();// 1. 不能new這個抽象類,只能靠子類去實現它;約束!// 2. 抽象類中可以寫普通的方法// 3. 抽象方法必須在抽象類中// 抽象的抽象:約束~
}
?抽象父類的子類,他里面有重寫父類的方法:
package com.oop.demo08;// 抽象類的所有方法,繼承了他的子類,都必須要實現他的方法
public class A extends Action {@Overridepublic void doSomething() {}
}
?
?
8.11 接口的定義與實現
?
接口的作用:1. 約束2. 定義一些方法,讓不同的人實現3. public abstract4. public static final5. 接口不能實例化,接口中沒有構造方法6. implements可以實現多個接口7. 必須要重寫接口中的方法
接口UserService:
package com.oop.demo09;//interface 定義接口的修飾符(關鍵字),接口都需要有實現類
public interface UserService {// 接口中定義就是常量 public static finalint AGE = 9999;// 接口中的所有定義的方法其實都是抽象的 public abstractvoid add(String name);void delete(String name);void update(String name);void query(String name);
}
?接口TimeService:
package com.oop.demo09;public interface TimeService {void timer();
}
????????每個接口都需要有實現類。我是這樣理解的,每個接口就是定義一堆方法的名字與類型就是沒有里面的內容,而他們需要有實現類來實現里面的內容,需要用到關鍵字implements:
package com.oop.demo09;// 類 可以實現接口 implements 接口
// 實現了接口的類,就需要重新接口中的方法// 利用接口實現多繼承
public class UersServiceImpl implements UserService,TimeService{@Overridepublic void add(String name) {}@Overridepublic void delete(String name) {}@Overridepublic void update(String name) {}@Overridepublic void query(String name) {}@Overridepublic void timer() {}
}
?
?
8.12 N種內部類
package com.oop.demo10;public class Outer {private int id = 14203;public void out(){System.out.println("這是外部類的方法");}public class Inner{public void in(){System.out.println("這是內部類的方法");}// 內部類能夠獲得外部類的私有屬性public void getID(){System.out.println(id);}}
}
import com.oop.demo10.Outer;import java.util.Optional;public class AppLication{public static void main(String[] args) {Outer outer = new Outer();// 通過這個外部類來實例化內部類Outer.Inner inner = outer.new Inner();inner.in();inner.getID();}
}
?局部內部類:
package com.oop.demo10;public class Outer {// 局部內部類,在方法里的屬性也叫做局部變量public void method(){class Inner{}}
}
匿名內部類:
package com.oop.demo10;public class Test {public static void main(String[] args) {// 沒有名字初始化類,匿名類// 不用將實例保存在對象中new Apple();new Apple().eat();// 甚至可以匿名一個接口new Userservice(){@Overridepublic void happle() {}};}
}class Apple{public void eat(){System.out.println("eat");}
}interface Userservice{void happle();
}