深入解析Java多態(tài)進階學習
1.動態(tài)綁定機制
java的動態(tài)綁定機制非常重要
實例A
我們來看一個實例:

閱讀上面的代碼,請說明下面的程序?qū)⑤敵鍪裁唇Y(jié)果:

程序?qū)敵?0和30,這個實例很簡單,直接看運行類型即可,該代碼的運行類型為B,所以會調(diào)用B類的方法
實例B
我們將上面的代碼變通一下,將子類中的如下代碼塊注銷:

隨后繼承機制會訪問父類的sum方法:

那么這里有一個問題,此處的getI(),會執(zhí)行子類的還是父類的呢?
當調(diào)用對象方法的時候,該方法會和該對象的內(nèi)存地址/運行類型綁定
代碼的運行類型依然是B,所以此處會執(zhí)行子類的getI()方法,結(jié)果輸出為30
實例C
現(xiàn)在我們再變通以下上面的代碼
再將子類中如下的代碼塊注銷:

繼承機制會執(zhí)行父類的sum1方法:

那么這里有一個問題,此處的i,會使用子類的還是父類的呢?
屬性沒有動態(tài)綁定機制,哪里聲明,哪里使用(使用當前類的)
此處的i在父類進行聲明,所以會選用父類的i屬性,結(jié)果為20
2.多態(tài)數(shù)組
定義:
數(shù)組的定義類型為父類類型,但是保存的實際元素類型為子類類型
Person父類:
/**
* 多態(tài)數(shù)組父類
*/
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
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 String say() {
return name + '\t' + age;
}
}
Student子類:
/**
* 多態(tài)數(shù)組學生子類
*/
public class Student extends Person{
private double score;
public Student(String name, int age, double score) {
super(name, age);
this.score = score;
}
// 重寫父類的say方法
public String say() {
return super.say() + '\t' + score;
}
}
Teacher子類:
/**
* 多態(tài)數(shù)組教師子類
*/
public class Teacher extends Person {
private double sal;
public Teacher(String name, int age, double sal) {
super(name, age);
this.sal = sal;
}
public double getSal() {
return sal;
}
public void setSal(double sal) {
this.sal = sal;
}
public String say() {
return super.say() + '\t' + sal;
}
}
測試多態(tài)數(shù)組的使用:
public class Test {
public static void main(String[] args) {
// 多態(tài)數(shù)組的使用
Person[] persons = new Person[5];
persons[0] = new Person("dahe",20);
persons[1] = new Student("wangwei",11,100);
persons[2] = new Student("zhangsan",12,60);
persons[3] = new Teacher("wang",33,15000);
persons[4] = new Teacher("li",55,25000);
// 循環(huán)遍歷多態(tài)數(shù)組,調(diào)用say方法
for (int i = 0; i < persons.length; i++) {
String out = persons[i].say(); // 動態(tài)綁定機制,編譯類型永遠都是Person
// 運行類型是根據(jù)實際情況由JVM機決定
System.out.println(out);
}
}
}
輸出:
dahe 20
wangwei 11 100.0
zhangsan 12 60.0
wang 33 15000.0
li 55 25000.0
3.多態(tài)數(shù)組的高階用法
現(xiàn)在,教師子類新增了教學方法:
public void teach() {
System.out.println("老師:" + getName() + "正在講課!");
}
學生子類新增了學習方法:
public void study() {
System.out.println("學生:" + getName() + "正在學習!");
}
那么,有沒有辦法通過多態(tài)數(shù)組來訪問他們子類對應(yīng)的獨有的方法呢?事實上,可以通過巧妙使用instanceof來解決:
變通一下,改變多態(tài)數(shù)組的循環(huán)操作:
// 循環(huán)遍歷多態(tài)數(shù)組,調(diào)用say方法
for (int i = 0; i < persons.length; i++) {
String out = persons[i].say(); // 動態(tài)綁定機制,編譯類型永遠都是Person
// 運行類型是根據(jù)實際情況由JVM機決定
System.out.println(out);
if (persons[i] instanceof Student) {
// 向下轉(zhuǎn)型
Student student = (Student) persons[i];
student.study();
} else if (persons[i] instanceof Teacher) {
Teacher teacher = (Teacher) persons[i];
teacher.teach();
}
}
輸出:
dahe 20
wangwei 11 100.0
學生:wangwei正在學習!
zhangsan 12 60.0
學生:zhangsan正在學習!
wang 33 15000.0
老師:wang正在講課!
li 55 25000.0
老師:li正在講課!
大功告成!多態(tài)數(shù)組即強大又完美!
4.多態(tài)參數(shù)
方法定義的形參類型為父類類型,實參類型允許為子類類型
接下來我們來演示以下多態(tài)參數(shù)的使用:
父類:
/**
* 多態(tài)參數(shù) - 父類
*/
public class Employee {
private String name;
private double sal;
public Employee(String name, double sal) {
this.name = name;
this.sal = sal;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSal() {
return sal;
}
public void setSal(double sal) {
this.sal = sal;
}
// 得到年工資的方法
public double getAnnual() {
return 12 * sal;
}
}
員工子類:
/**
* 多態(tài)參數(shù) - 子類員工
*/
public class Worker extends Employee{
public Worker(String name, double sal) {
super(name, sal);
}
public void work() {
System.out.println("普通員工:" + getName() + "正在工作!");
}
public double getAnnual() {
return super.getAnnual();
}
}
經(jīng)理子類:
/**
* 多態(tài)參數(shù) - 經(jīng)理子類
*/
public class Manager extends Employee{
private double bonus; // 獎金
public Manager(String name, double sal, double bonus) {
super(name, sal);
this.bonus = bonus;
}
public double getBonus() {
return bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
public void manage() {
System.out.println("經(jīng)理:" + getName() + "正在管理!");
}
@Override
public double getAnnual() {
return super.getAnnual() + bonus;
}
}
我們來測試一下,求不同崗位的雇員的年薪:
/**
* 多態(tài)參數(shù)測試類
*/
public class Test {
public static void main(String[] args) {
Worker zhang = new Worker("張工",1000);
Manager milan = new Manager("milan", 5000, 2000);
Test test = new Test();
test.showEmpAnnual(zhang);
test.showEmpAnnual(milan);
}
// 獲取員工的年薪,采用多態(tài)參數(shù)
public void showEmpAnnual(Employee e) {
System.out.println(e.getAnnual());
}
}
輸出:
12000.0
62000.0
5.多態(tài)參數(shù)的高階用法
我們來對上面的多態(tài)參數(shù)代碼做一個完善,如果傳入的是員工,則調(diào)用自己的work方法,如果傳入的是經(jīng)理,則調(diào)用自己的manage方法
增加一個下面的方法:
public void testWork(Employee e) {
if (e instanceof Worker) {
((Worker) e).work(); // 向下轉(zhuǎn)型
} else if (e instanceof Manager) {
((Manager) e).manage();
}
}
測試:
test.testWork(zhang); test.testWork(milan);
輸出:
普通員工:張工正在工作!
經(jīng)理:milan正在管理!
到此這篇關(guān)于深入解析Java多態(tài)進階學習的文章就介紹到這了,更多相關(guān)Java多態(tài)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot @Scope與@RefreshScope注解使用詳解
spring的bean管理中,每個bean都有對應(yīng)的scope。在BeanDefinition中就已經(jīng)指定scope,默認的RootBeanDefinition的scope是prototype類型,使用@ComponentScan掃描出的BeanDefinition會指定是singleton,最常使用的也是singleton2022-11-11
Java?guava框架LoadingCache及CacheBuilder本地小容量緩存框架總結(jié)
Guava?Cache本地緩存框架主要是一種將本地數(shù)據(jù)緩存到內(nèi)存中,但數(shù)據(jù)量并不能太大,否則將會占用過多的內(nèi)存,本文給大家介紹Java?guava框架?LoadingCache及CacheBuilder?本地小容量緩存框架總結(jié),感興趣的朋友一起看看吧2023-12-12
java爬蟲之使用HttpClient模擬瀏覽器發(fā)送請求方法詳解
這篇文章主要介紹了java爬蟲之使用HttpClient模擬瀏覽器發(fā)送請求方法詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-07-07

