這次是2021年01月19日的學習成果,總結于此,以便于之后的學習查漏補缺
目錄
- 多型(重點)
- 多型概述
- 多型的實作條件
- 多型實作基礎
- 多型的作用
- 多型的總結
- 多型的轉型
- 向上轉型upcasting
- 向下轉型downcasting
- 轉型實體:
- 型別轉換的重點:
- 多型與instanceof
- 多型的應用場景
- 基于繼承的多型
- 基于介面的多型
- 函式輸入引數的多型
- 函式回傳值的多型
- 內部類
- 1、概述
- 2、成員內部類
- (1)定義成員內部類
- (2)成員內部類的使用
- 小結:
- 5、匿名物件(掌握)
- 6、匿名內部類(掌握)
多型(重點)
多型概述
生活實體
實體1:
水果:蘋果,香蕉,西瓜
實體2:
動物:老虎,獅子,大象
實體3:
動物叫:貓叫,牛叫,羊叫
總結:多型即為多種形態,狀態
多型的實作條件
Java實作多型的必要條件:繼承、重寫,
當編譯時型別和運行時型別不一致,就會出現多型(Polymorphism)
創建人的類(父類)
public class Person {
private String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void eat() {
System.out.println("人吃飯");
}
public void sleep() {
System.out.println("人睡覺");
}
}
創建男孩類(子類)
public class Boy extends Person{
private String ID;
public Boy() {
super();
}
public Boy(String name, int age) {
super(name, age);
}
public Boy(String name, int age, String iD) {
super(name, age);
ID = iD;
}
public void play() {
System.out.println("男孩去打游戲");
}
@Override
public String getName() {
return super.getName();
}
@Override
public void setName(String name) {
super.setName(name);
}
@Override
public int getAge() {
return super.getAge();
}
@Override
public void setAge(int age) {
super.setAge(age);
}
@Override
public void eat() {
System.out.println("男孩在狼吞虎咽地吃飯");
}
@Override
public void sleep() {
System.out.println("男孩聽著音樂睡覺");
}
}
創建女孩類(子類)
public class Girl extends Person{
private String number;
public Girl() {
super();
}
public Girl(String name, int age) {
super(name, age);
}
public Girl(String name, int age, String number) {
super(name, age);
this.number = number;
}
public void buy() {
System.out.println("女孩在買東西");
}
@Override
public String getName() {
return super.getName();
}
@Override
public void setName(String name) {
super.setName(name);
}
@Override
public int getAge() {
return super.getAge();
}
@Override
public void setAge(int age) {
super.setAge(age);
}
@Override
public void eat() {
System.out.println("女孩在斯文的吃飯");
}
@Override
public void sleep() {
System.out.println("女孩在安靜地睡覺");
}
}
測驗類
import java.awt.GridBagConstraints;
public class Test {
public static void main(String[] args) {
Person person1 = new Person();
person1.eat();
System.out.println("-------------");
Boy boy = new Boy("小明", 20);
boy.eat();
boy.sleep();
boy.play();
System.out.println("-------------");
Girl girl = new Girl();
girl.eat();
girl.sleep();
girl.buy();
System.out.println("-------------");
Person person2 = new Boy("李華",21);
person2.eat();
person2.sleep();
System.out.println("-------------");
Person person3 = new Girl();
person3.eat();
person3.sleep();
}
}
運行結果

多型實作基礎
父類宣告的變數可以參考所有子類的物件,這是多型實作的基礎,
我們只有在 運行 的時候才會知道參考變數所指向的具體實體物件,
多型的作用
把不同的子類物件都當作父類來看,可以屏蔽不同子類物件之間的差異,寫出通用的代碼,做出通用的編程,以適應需求的不斷變化,簡單的說,就是用父類或介面的參考變數指向子類的物件,
多型的總結
在涉及多型的編程中,請注意以下細節:
1、靜態方法
靜態方法不能被重寫,所以靜態方法也沒有多型性.
2、 成員變數
成員變數不具備多型性,成員變數的值取決于參考所屬的類
3、成員方法
編譯時:檢查參考變數所屬類中是否有所呼叫的方法,運行時:呼叫實際物件所屬類中的重寫方法,
多型的轉型
在多變編程中涉及到參考資料型別之間的轉換,
向上轉型upcasting
向上轉型就是子類轉父類,這是由系統自動完成,
請注意:一個參考型別變數如果宣告為父類的型別,但實際參考的是子類物件,那么該變數就不能再訪問子類中特有的屬性和方法
Person person2 = new Boy("李華",21);
person2.eat();
person2.sleep();
//The method play() is undefined for the type Person
//play這個方法沒有為Person類定義
//person2.play();
System.out.println("-------------");
Person person3 = new Girl();
person3.eat();
person3.sleep();
//The method buy() is undefined for the type Person
//buy這個方法沒有為Person類定義
//person3.buy();
那么,怎么解決,子類轉為父類無法呼叫自己的方法,這個問題呢,使用先下面的強制型別轉換符 ()
向下轉型downcasting
向下轉型就是父類轉子類,此時需要使用強制型別轉換符 ()
Person person2 = new Boy("李華",21);
//父類物件強轉為子類物件
Boy boy1 = (Boy) person2;
boy1.eat();
boy1.sleep();
//The method play() is undefined for the type Person
boy1.play();
System.out.println("-------------");
Person person3 = new Girl();
//父類物件強轉為子類物件
Girl girl1 = (Girl)person3;
girl1.eat();
girl1.sleep();
//The method buy() is undefined for the type Person
girl1.buy();
運行結果:

轉型實體:
//父類參考指向子類物件
Person person4 = new Boy();
person4.eat();
//Error code
//person4.play();
型別轉換的重點:
1、弄清楚繼承關系、誰是父類誰是子類
2、關鍵點在于創建物件時呼叫的是誰的建構式
多型與instanceof
在多型編程中可以通過instanceof判斷物件到除錯于哪個確切的型別
boolean result = boy instanceof Boy;
System.out.println(result);
result = person1 instanceof Person;
System.out.println(result);
運行結果:

運用if陳述句判斷,避免 子類轉為父類無法呼叫自己的方法
Person person2 = new Boy("李華",21);
if(person2 instanceof Boy) {
((Boy) person2).play();
}
多型的應用場景
基于繼承的多型
多個子類對同一方法的重寫,可以在運行時表現出不同的行為
基于介面的多型
一個介面可以有多 個實作類,所以,多個實作類對介面中同一方法的重寫,可以在運行時表現出不同的行為,
場景: 介面名 變數名 = new 類名()
MyClass myClass = new MyClass();
MyInterface myInterface = new MyClass();
注意:命名規范,介面名 —> 介面名Impl
public class MyInterfaceImpl implements MyInterface {
}
函式輸入引數的多型
多型可以作為形參,接受范圍更廣的物件,接受的引數更加靈活
public static void main(String[] args) {
Person person5 = new Person();
test1(person5);
}
public static void test1(Person person5) {
if(person5 instanceof Boy) {
((Boy) person5).Play();
}
if(person5 instanceof Girl) {
((Girl) person5).buy();
}
}
public static void main(String[] args) {
MyInterface myInterface = new MyInterfaceImpl();
test2(myInterface);
}
public static void test2(MyInterface myInterface) {
}
函式回傳值的多型
多型可以作為回傳值,接受范圍更廣的物件
public 父類 方法名(){
return 父類物件;
return 子類物件;
}
public static Person test1() {
Person person = new Person();
Boy boy = new Boy();
Girl girl = new Girl();
return girl;
}
public static MyInterface test3() {
MyInterfaceImpl myInterfaceImpl = new MyInterfaceImpl();
return myInterfaceImpl;
}
public static Fruit test4() {
return new Apple;
}
內部類
1、概述
在一個類的內部定義的類稱為內部類,其實就是類定義的位置發生了變化,在類中定義的內部類叫成員內部類,在函式中定義的內部類叫區域內部類,使用static 修飾的成員內部類叫靜態內部類,靜態內部類使用很少,用的最多的是成員內部類,
注意:內部類生產的class檔案為 “ 外部類$內部類 ”, 它表明該內部類是屬于哪個外部類的,
2、成員內部類
(1)定義成員內部類
1、成員內部類也是一個類,可以有自己的成員屬性、成員方法,
2、成員內部類可以訪問外部類的成員方法和成員屬性,
3、在內部類中,this.name中的this表示內部類
小結
內部類訪問外部類的欄位:外部類類名.this.欄位
內部類訪問外部類的方法:外部類類名.this.方法.
內部類訪問內部類欄位: this.欄位
內部類訪問內部類方法: this.方法
//外部類
public class Forest {
private int treeType;
public int getTreeType() {
return treeType;
}
public void setTreeType(int treeType) {
this.treeType = treeType;
}
public static void printTree() {
System.out.println("好樹!好樹啊!");
}
//內部類
class Animal{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getTreeType() {
//訪問外部屬性
int type = Forest.this.getTreeType();
return type;
}
}
}
(2)成員內部類的使用
成員內部類必須依賴于外部類的物件,
所以,首先創建外部類,然后使用外部類的實體創建普通內部類,
示例如下:
第一種寫法:
//創建外部物件
Forest forest = new Forest();
//創建內部類物件
Forest.Animal animal = forest.new Animal();
//內部類物件呼叫方法
int number = animal.getTreeType();
System.out.println(number);
第二種寫法:
Forest.Animal animal = new Forest().new Animal();
int number = animal.getTreeType();
System.out.println(number);
小結:
內部類的訪問特點:
1、內部類可以直接訪問外部類的成員,包括外部類的私有物件,
2、外部類要訪問內部類的成員,必須創建物件,
5、匿名物件(掌握)
1、沒有名字
2、僅能使用一次
//匿名物件,直接呼叫方法,只能用一次
new Forest().printTree();
6、匿名內部類(掌握)
匿名內部類是-種特殊的內部類,它在陳述句內部定義,沒有類名,例如:在GUI程式中作為事件處理函式,
匿名內部類必須繼承-個父類或者是實作一個介面,語法格式:
new 父類或者介面(){
執行代碼...
};
每次創建匿名內部類的物件時,必須先定義匿名內部類,然后馬上使用new創建物件,如果希望再次創建這個匿名內部類的物件,必須重定定義匿名內部類,即每個匿名內部類的定義只能使用一次,
定義介面:
public interface MyInterface1 {
void sayHello();
}
public class MyInterface1Impl implements MyInterface1{
@Override
public void sayHello() {
System.out.println("Hello 好好學習");
}
}
測驗程式:
public class Test1 {
public static void main(String[] args) {
Test1 demo = new Test1();
MyInterface1Impl myInterface1Impl = new MyInterface1Impl();
myInterface1Impl.sayHello();
demo.test(myInterface1Impl);
System.out.println("---------");
// 下面括號里new開始到});就是一個物件
demo.test(new MyInterface1() {
@Override
public void sayHello() {
System.out.println("大家好");
}
});
}
public void test(MyInterface1 myinterface1) {
myinterface1.sayHello();
}
}
運行結果:

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/264828.html
標籤:java
