接口回調是指:能夠把使用實現了某一接口的類建立的對象的引用賦給該接口聲明的接口變量,那麼該接口變量就能夠調用被類實現的接口的方法。實際上,當接口變量調用被類實現的接口中的方法時,就是通知相應的對象調用接口的方法,這一過程稱爲對象功能的接口回調。看下面示例。
interface People {
void peopleList();
}
class Student implements People {
publicvoid peopleList() {
System.out.println("I’m a student.");
}
}
class Teacher implements People {
publicvoid peopleList() {
System.out.println("I’m a teacher.");
}
}
publicclass Example {
publicstaticvoid main(String args[]) {
People a; // 聲明接口變量
a = new Student(); // 實例化,接口變量中存放對象的引用
a.peopleList(); // 接口回調
a = new Teacher(); // 實例化,接口變量中存放對象的引用
a.peopleList(); // 接口回調
}
} java
I’m a student.
I’m a teacher.
再來看看向上轉型(upcasting)的概念。編程
Shape s=new Circle(); 安全
這裏,建立了一個Circle對象,並把獲得的引用當即賦值給Shape。經過繼承,Circle就是一種Shape。
假設你調用基類方法(它已在導出類中被覆蓋):
s.draw(); ide
因爲後期綁定(多態),將會正確調用Circle.draw()方法。spa
在java裏面,關於跨類引用,有兩條規則應該記住:
1)若是a是類A的一個引用,那麼,a能夠指向類A的一個實例。或者說指向類A的一個子類,這是向上轉型的情形。
2)若是a是接口A的一個引用,那麼,a必須指向實現了接口A的一個類的實例。這是接口回調的情形。
在java裏面,向上轉型是自動進行的,可是向下轉型卻不是,對象
須要咱們本身定義強制進行.
class B extends A{}
publicclass A {
publicstaticvoid main(String[] argts){
A a1=new A();
A a2=new B();//Upcasting向上轉型
B b1=new B();
B b2=(B) new A();//DownCasting向下轉型,[注意]:此處(B)進行了強制轉換!
}
} 繼承
從實現了某接口的對象,獲得對此接口的引用,與向上轉型爲這個對象的基類,實質上效果是同樣的。這些對象均可以調用基類型提供的方法,對於接口來講就是回調接口中的方法,對於父類來講就是調用父類的方法。固然在向上轉型的狀況下,還牽涉到子類重寫(Override)父類方法的情形。接口
轉型是在繼承的基礎上而言的,繼承是面嚮對象語言中,代碼複用的一種機制,經過繼承,子類能夠複用父類的功能,若是父類不能知足當前子類的需求,則子類能夠重寫父類中的方法來加以擴展。io
向上轉型:子類引用的對象轉換爲父類類型稱爲向上轉型。通俗地說就是是將子類對象轉爲父類對象。此處父類對象能夠是接口編譯
向下轉型:父類引用的對象轉換爲子類類型稱爲向下轉型。
前者是一個向上轉型,Animal dog 引用指向new Dog();子類對象當成父類對象,只能調用父類的成員,若是子類重寫了父類的方法就根據這個引用指向調用子類重寫的這個方法(這個方法就是覆蓋override)。這個調用過程就稱爲「動態綁定」。
轉型須要注意的問題:
向上轉型時,父類指向子類引用對象會遺失除與父類對象共有的其餘方法,也就是在轉型過程當中,子類的新有的方法都會遺失掉,在編譯時,系統會提供找不到方法的錯誤。實例以下:
public class Animal {
public void eat(){
System.out.println("animal eatting...");
}
}
class Bird extends Animal{
public void eat(){
System.out.println("bird eatting...");
}
public void fly(){
System.out.println("bird flying...");
}
}
class Main{
public static void main(String[] args) {
Animal b=new Bird(); //向上轉型
b.eat();
b.fly(); //此處提示在Animal中沒有定義fly方法。
}
在向下轉型過程當中,分爲兩種狀況:
狀況一:若是父類引用的對象若是引用的是指向的子類對象,那麼在向下轉型的過程當中是安全的。也就是編譯是不會出錯誤的。
狀況二:若是父類引用的對象是父類自己,那麼在向下轉型的過程當中是不安全的,編譯不會出錯,可是運行時會出現java.lang.ClassCastException錯誤。它可使用instanceof來避免出錯此類錯誤。實例以下:
public class Girl {
public void smile(){
System.out.println("girl smile()...");
}
}
class MMGirl extends Girl{
@Override
public void smile() {
System.out.println("MMirl smile sounds sweet...");
}
public void c(){
System.out.println("MMirl c()...");
}
}
class main{
public static void main(String[] args) {
Girl g1=new MMGirl(); //向上轉型
g1.smile();
MMGirl mmg=(MMGirl)g1; //向下轉型,編譯和運行皆不會出錯
mmg.smile();
mmg.c();
Girl g2=new Girl();
//MMGirl mmg1=(MMGirl)g2; //不安全的向下轉型,編譯無錯但會運行會出錯
//mmg1.smile();
//mmg1.c();
if(g2 instanceof MMGirl){
MMGirl mmg1=(MMGirl)g2;
mmg1.smile();
mmg1.c();
}
}
總結:
一、父類引用能夠指向子類對象,子類引用不能指向父類對象。
二、把子類對象直接賦給父類引用叫upcasting向上轉型,向上轉型不用強制轉型。
如Father father = new Son();
三、把指向子類對象的父類引用賦給子類引用叫向下轉型(downcasting),要強制轉型。
如father就是一個指向子類對象的父類引用,把father賦給子類引用son 即Son son =(Son)father;
其中father前面的(Son)必須添加,進行強制轉換。
四、upcasting 會丟失子類特有的方法,可是子類overriding 父類的方法,子類方法有效
五、向上轉型的做用,減小重複代碼,父類爲參數,調有時用子類做爲參數,就是利用了向上轉型。這樣使代碼變得簡潔。體現了JAVA的抽象編程思想。