### 概念
多態是繼封裝(安全性)、繼承(復用)之后,面向對象的第三大特性。
1. 現實事物經常會體現出多種形態,如學生,學生是人的一種,則一個具體的同學張三既是學生也是人,即出現兩種形態。
2. Java作為面向對象的語言,同樣可以描述一個事物的多種形態。如Student類繼承了Person類,一個Student的對象便既是Student,又是Person。
3. Java中多態的代碼體現在一個子類對象(實現類對象)既可以給這個子類(實現類對象)引用變量賦值,又可以給這個子類(實現類對象)的父類(接口)變量賦值。
4. 如Student類可以為Person類的子類。那么一個Student對象既可以賦值給一個Student類型的引用,也可以賦值給一個Person類型的引用。
5. 最終多態體現為父類引用變量可以指向子類對象。
6. 多態的前提是必須有子父類關系或者類實現接口關系,否則無法完成多態。
7. 在使用多態后的父類引用變量調用方法時,會調用子類重寫后的方法。
8. 多態是指對象的多態(不是類),是指一個對象的多種狀態.
## 多態的前提
1. 必須有費子類關系.
2. 必須有方法被重寫.
語法 :
~~~
父類或接口類型 變量名 = new 子類(); //接口,抽象類和普通類都可以實現多態性
~~~
**成員變量**
1. 編譯的時候,參考父類中有沒有這個變量,如果有,編譯成功. 如果沒有則編譯失敗 .
2. 如果編譯成功,運行的時候,運行的是父類的變量值 .
3. 結論 : 編譯運行全看父類 .
父類
~~~
public class Parent {
public int x = 10;
}
~~~
子類
~~~
public class Son extends Parent {
public int x = 20;
}
~~~
調用
~~~
public class Main {
public static void main(String[] args)
{
Parent s = new Son();
System.out.print(s.x);
}
}
~~~
結果
~~~
10
~~~
**成員方法**
1. 編譯的時候,參考父類中有沒有這個方法,如果有,編譯成功; 如果沒有則編譯失敗 .
2. 運行的時候,運行的是子類的重寫方法 .
3. 結論 : 編譯看父類, 運行看子類(**如果是靜態方法,那么都是看父類 . 因為靜態是屬于類的,跟對象沒有關系**) .
父類方法
~~~
public class Parent {
public void show()
{
System.out.print("父類方法");
}
}
~~~
子類方法
~~~
public class Son extends Parent {
public void show()
{
System.out.print("子類方法");
}
}
~~~
調用
~~~
public class Main {
public static void main(String[] args)
{
Parent s = new Son();
s.show();
}
}
~~~
結果
~~~
子類方法
~~~
## 多態的弊端
1. 只能調用子父類共有的方法,不能調用子類特有的方法,編譯不能通過.
## 多態的優點
1. 提高了程序的靈活性.
## 總結
1. 父類類型變量,可以接收任何 一個子類類型的對象.
2. 調用方法的時候,編譯時看父類,運行時看子類.
### instanceof 運算符
~~~
實例對象 instanceof 類名; //結果是布爾值
~~~
## 實例
~~~
public abstract class AbstractAnimal
{
public abstract void eat();
}
~~~
~~~
public class Cat extends AbstractAnimal
{
@Override
public void eat()
{
System.out.println("貓吃飯");
}
}
~~~
~~~
public class Dog extends AbstractAnimal
{
@Override
public void eat()
{
System.out.println("狗吃飯");
}
}
~~~
調用
~~~
public class Test
{
public static void main(String[] args)
{
Dog d = new Dog();
feed(d);
Cat c = new Cat();
feed(c);
}
public static void feed(AbstractAnimal a)
{
a.eat();
}
}
~~~
### 向上轉型
~~~
Parent p = new Son()
~~~
**詳解**
1. 因為java強制規定,參與運算的數據類型必須一致, 但是在這里賦值號兩方類型明顯不一致 , 為什么能編譯成功呢 ? 因為java對Son() 進行了向上類型轉換 . 將Son 的類型轉換成Parent 了 .
2. 這個時候p所指向的引用數據類型無法調用Son類自己獨有的方法 , 只能調用對Parent類重寫的方法 .
### 向下轉型
轉型的作用是調用子類獨有向下的方法.
~~~
子類 變量 = (子類)父類變量;
~~~
**詳解**
1. 如果非要使用子類獨有的方法,那么怎么辦呢 ? 只能向下轉型, 向下轉型必須進行強制轉換 .
2. 進行向下轉型之后就可以使用子類獨有的方法了.
## 向下轉型弊端
向下轉型編譯器不會報錯,運行的時候就報錯了.
~~~
AbstractAnimal dog = new Dog();
cat c = (Cat) dog;
c.speak(); //貓沒有這個方法
~~~
## java解決向下轉型的弊端
使用instanceof 運算符.
- 環境
- Java基礎
- 數據類型
- 基本類型
- 引用類型
- Array
- Class
- ArrayList
- 流程控制
- ASCII碼表
- 面向對象
- 概述
- 變量
- this
- 修飾符
- 封裝
- 繼承
- final
- static
- 接口
- 接口
- 抽象類
- overload
- 接口和抽象類區別
- 案例
- 多態
- 構造方法
- super
- 匿名對象
- 內部類
- 靜態導入
- 包的聲明和訪問
- 代碼塊
- 代理設計模式
- 靜態代碼塊
- Object類
- lambda表達式
- 枚舉
- 定義枚舉
- 常用方法
- 枚舉常量
- 異常
- 可變參數
- Properties
- 概述
- Properties和持久化有關的方法
- 反射
- 類加載器
- 概述
- Class類
- 獲取構造方法并運行
- 獲取成員變量并改值
- 獲取成員方法并運行
- 反射泛型擦除
- 反射通過配置文件運行
- 常用 API
- Date類
- DateFormat類
- Calendar類
- Math類
- String類
- object類
- System類
- 正則表達式
- BigInteger類
- BigDecimal類
- Arrays工具類
- StringBuffer類
- 基本類型包裝類
- 自動裝箱和自動拆箱
- 框架集合
- collection接口
- 概述
- 接口方法
- 迭代器
- 迭代器并發異常
- 增強for循環
- 泛型
- hashCode和equals
- List接口
- 概述
- ArrayList
- LinkedList
- vector
- Set接口
- 概述
- 對象的哈希值
- HashSet
- LinkedHashSet
- 保證自定義元素的唯一性(重寫)
- ArrayList和HashSet的contains原理
- Map接口
- 概述
- Map集合常用方法
- 迭代Map
- Map存儲自定義類型
- HashMap
- LinkedHashMap
- Hashtable
- 嵌套Map遍歷
- 方法的可變參數
- collections工具類
- 集合嵌套
- 集合特點總結
- Collection集合工具類
- Arrays工具類
- File類
- 概述
- 獲取方法
- 創建和刪除
- 判斷方法
- 其他方法
- 文件過濾器
- IO流
- 字節流
- 概述
- 字節流
- 字節流復制文件
- 字節緩沖流
- 復制單級文件夾
- 使用字節流讀取中文的亂碼問題
- 字符編碼表
- 方便程序員的IO流
- 轉換流
- 概述
- OutputStreamWriter類
- InputStreamWriter類
- 轉換流和其他子類的區別
- 序列化流
- 概述
- 序列化接口以及版本號問題
- transient
- 打印流
- 多線程
- 概述
- main線程介紹
- 開啟線程方式一:Thread類
- 開啟線程方式二:Runnable類
- 線程的執行原理
- 使用哪種方式好
- 使用匿名內部類創建線程
- 線程安全
- ThreadLocal
- 網絡編程
- XML
- 概述
- 語法
- 元素標簽
- 屬性
- 轉義字符
- CDATA區
- XML約束
- DTD約束
- 三種引入DTD的方式
- DTD語法
- Schema約束
- JDBC
- 概述
- JDBC原理
- JDBC查詢操作
- JDBCUtils
- 預處理對象
- JDBC連接池
- 概述
- DBCP
- C3P0
- DBUtils操作
- ArrayHandler
- ArrayListHandler
- BeanHandler
- BeanListHandler
- ColumnListHandler
- MapHandler
- MapListHandler
- ScalarHandler
- 事務
- 事務概述
- 原生JDBC完成轉賬
- DBUtils完成轉賬
- 事務特性
- 三層思想
- 概述
- JavaWEB
- tomcat
- servlet
- 概述
- 映射servlet
- Servlet接口
- HttpServlet類
- load-on-startup
- servletContext
- ServletRequest
- ServletResponse
- Cooike&Session
- servlet三大域對象
- JSP
- 概述
- jsp內置對象
- 指令
- page
- include
- taglib
- JSP中的四個域對象
- jsp的一個動作標簽
- EL表達式
- 概述
- 獲取域中數據
- 執行運算
- el表達式中的內置對象
- jsti標簽
- 概念
- jstl分類
- Filter過濾器
- 概述
- 生命周期
- url-pattern配置
- filter的chain過濾鏈
- filter-mapping子標簽
- 全局統一錯誤頁面
- filterConfig
- 自動登錄實例
- 全局統一編碼
- Listener監聽器
- 概念
- 監聽器分類
- 監聽三個對象的創建和銷毀
- 監聽三個對象屬性的變化
- 監聽javabean在session中的狀態變化
- 定時器
- 概念
- calendar日歷
- 郵件
- 概述
- JSON
- 數據結構
- 堆棧結構
- 隊列結構
- 數組結構
- 鏈表結構
- 基礎加強
- 面試題:增強一個對象的方法有幾種方式?
- 裝飾者增強
- 動態代理
- 動態代理
- 動態代理細節
- 使用動態代理解決字符集編碼
- 注解
- 概述
- 擴展的自定義注解
- 類加載器
- 全盤負責托管機制
- 開發模式
- 問題
- lambda
- 函數式編程思想概述
- String字符串